From 7315095e464397ae3f4dc9f1d231278e61242b04 Mon Sep 17 00:00:00 2001 From: david gauchard Date: Wed, 1 Nov 2017 22:12:20 +0100 Subject: [PATCH] lwip2: build: include and lib --- tools/sdk/lib/liblwip2.a | Bin 0 -> 1039116 bytes tools/sdk/lwip2/include/README.md | 1 + tools/sdk/lwip2/include/arch/cc.h | 145 + tools/sdk/lwip2/include/arch/sys_arch.h | 5 + tools/sdk/lwip2/include/espconn.h | 0 tools/sdk/lwip2/include/gluedebug.h | 89 + tools/sdk/lwip2/include/lwip-err-t.h | 10 + tools/sdk/lwip2/include/lwip-git-hash.h | 6 + tools/sdk/lwip2/include/lwip/api.h | 400 +++ tools/sdk/lwip2/include/lwip/apps/FILES | 2 + tools/sdk/lwip2/include/lwip/apps/fs.h | 103 + tools/sdk/lwip2/include/lwip/apps/httpd.h | 236 ++ .../sdk/lwip2/include/lwip/apps/httpd_opts.h | 323 ++ tools/sdk/lwip2/include/lwip/apps/lwiperf.h | 84 + tools/sdk/lwip2/include/lwip/apps/mdns.h | 69 + tools/sdk/lwip2/include/lwip/apps/mdns_opts.h | 74 + tools/sdk/lwip2/include/lwip/apps/mdns_priv.h | 66 + tools/sdk/lwip2/include/lwip/apps/mqtt.h | 244 ++ tools/sdk/lwip2/include/lwip/apps/mqtt_opts.h | 103 + tools/sdk/lwip2/include/lwip/apps/netbiosns.h | 43 + .../lwip2/include/lwip/apps/netbiosns_opts.h | 59 + tools/sdk/lwip2/include/lwip/apps/snmp.h | 128 + tools/sdk/lwip2/include/lwip/apps/snmp_core.h | 364 ++ tools/sdk/lwip2/include/lwip/apps/snmp_mib2.h | 78 + tools/sdk/lwip2/include/lwip/apps/snmp_opts.h | 293 ++ .../sdk/lwip2/include/lwip/apps/snmp_scalar.h | 113 + .../sdk/lwip2/include/lwip/apps/snmp_table.h | 134 + .../lwip2/include/lwip/apps/snmp_threadsync.h | 114 + tools/sdk/lwip2/include/lwip/apps/snmpv3.h | 90 + tools/sdk/lwip2/include/lwip/apps/sntp.h | 76 + tools/sdk/lwip2/include/lwip/apps/sntp_opts.h | 173 + tools/sdk/lwip2/include/lwip/apps/tftp_opts.h | 105 + .../sdk/lwip2/include/lwip/apps/tftp_server.h | 94 + tools/sdk/lwip2/include/lwip/arch.h | 319 ++ tools/sdk/lwip2/include/lwip/autoip.h | 99 + tools/sdk/lwip2/include/lwip/debug.h | 167 + tools/sdk/lwip2/include/lwip/def.h | 141 + tools/sdk/lwip2/include/lwip/dhcp.h | 143 + tools/sdk/lwip2/include/lwip/dhcp6.h | 58 + tools/sdk/lwip2/include/lwip/dns.h | 130 + tools/sdk/lwip2/include/lwip/err.h | 119 + tools/sdk/lwip2/include/lwip/errno.h | 193 ++ tools/sdk/lwip2/include/lwip/etharp.h | 106 + tools/sdk/lwip2/include/lwip/ethip6.h | 68 + tools/sdk/lwip2/include/lwip/icmp.h | 110 + tools/sdk/lwip2/include/lwip/icmp6.h | 70 + tools/sdk/lwip2/include/lwip/igmp.h | 115 + tools/sdk/lwip2/include/lwip/inet.h | 172 + tools/sdk/lwip2/include/lwip/inet_chksum.h | 105 + tools/sdk/lwip2/include/lwip/init.h | 100 + tools/sdk/lwip2/include/lwip/ip.h | 319 ++ tools/sdk/lwip2/include/lwip/ip4.h | 111 + tools/sdk/lwip2/include/lwip/ip4_addr.h | 227 ++ tools/sdk/lwip2/include/lwip/ip4_frag.h | 100 + tools/sdk/lwip2/include/lwip/ip6.h | 93 + tools/sdk/lwip2/include/lwip/ip6_addr.h | 285 ++ tools/sdk/lwip2/include/lwip/ip6_frag.h | 120 + tools/sdk/lwip2/include/lwip/ip_addr.h | 407 +++ tools/sdk/lwip2/include/lwip/mem.h | 82 + tools/sdk/lwip2/include/lwip/memp.h | 155 + tools/sdk/lwip2/include/lwip/mld6.h | 99 + tools/sdk/lwip2/include/lwip/nd6.h | 84 + tools/sdk/lwip2/include/lwip/netbuf.h | 118 + tools/sdk/lwip2/include/lwip/netdb.h | 150 + tools/sdk/lwip2/include/lwip/netif.h | 474 +++ tools/sdk/lwip2/include/lwip/netifapi.h | 140 + tools/sdk/lwip2/include/lwip/opt.h | 2876 ++++++++++++++++ tools/sdk/lwip2/include/lwip/pbuf.h | 263 ++ tools/sdk/lwip2/include/lwip/priv/api_msg.h | 216 ++ tools/sdk/lwip2/include/lwip/priv/memp_priv.h | 183 + tools/sdk/lwip2/include/lwip/priv/memp_std.h | 146 + tools/sdk/lwip2/include/lwip/priv/nd6_priv.h | 144 + tools/sdk/lwip2/include/lwip/priv/tcp_priv.h | 507 +++ .../sdk/lwip2/include/lwip/priv/tcpip_priv.h | 160 + tools/sdk/lwip2/include/lwip/prot/autoip.h | 78 + tools/sdk/lwip2/include/lwip/prot/dhcp.h | 183 + tools/sdk/lwip2/include/lwip/prot/dns.h | 140 + tools/sdk/lwip2/include/lwip/prot/etharp.h | 91 + tools/sdk/lwip2/include/lwip/prot/ethernet.h | 170 + tools/sdk/lwip2/include/lwip/prot/icmp.h | 91 + tools/sdk/lwip2/include/lwip/prot/icmp6.h | 170 + tools/sdk/lwip2/include/lwip/prot/igmp.h | 90 + tools/sdk/lwip2/include/lwip/prot/ip.h | 51 + tools/sdk/lwip2/include/lwip/prot/ip4.h | 127 + tools/sdk/lwip2/include/lwip/prot/ip6.h | 169 + tools/sdk/lwip2/include/lwip/prot/mld6.h | 70 + tools/sdk/lwip2/include/lwip/prot/nd6.h | 277 ++ tools/sdk/lwip2/include/lwip/prot/tcp.h | 97 + tools/sdk/lwip2/include/lwip/prot/udp.h | 68 + tools/sdk/lwip2/include/lwip/raw.h | 118 + tools/sdk/lwip2/include/lwip/sio.h | 142 + tools/sdk/lwip2/include/lwip/snmp.h | 213 ++ tools/sdk/lwip2/include/lwip/sockets.h | 593 ++++ tools/sdk/lwip2/include/lwip/stats.h | 491 +++ tools/sdk/lwip2/include/lwip/sys.h | 455 +++ tools/sdk/lwip2/include/lwip/tcp.h | 433 +++ tools/sdk/lwip2/include/lwip/tcpip.h | 106 + tools/sdk/lwip2/include/lwip/timeouts.h | 121 + tools/sdk/lwip2/include/lwip/udp.h | 182 + tools/sdk/lwip2/include/lwipopts.h | 3002 +++++++++++++++++ tools/sdk/lwip2/include/netif/etharp.h | 3 + tools/sdk/lwip2/include/netif/ethernet.h | 77 + tools/sdk/lwip2/include/netif/lowpan6.h | 86 + tools/sdk/lwip2/include/netif/lowpan6_opts.h | 70 + tools/sdk/lwip2/include/netif/ppp/ccp.h | 156 + tools/sdk/lwip2/include/netif/ppp/chap-md5.h | 36 + tools/sdk/lwip2/include/netif/ppp/chap-new.h | 192 ++ tools/sdk/lwip2/include/netif/ppp/chap_ms.h | 44 + tools/sdk/lwip2/include/netif/ppp/eap.h | 169 + tools/sdk/lwip2/include/netif/ppp/ecp.h | 50 + tools/sdk/lwip2/include/netif/ppp/eui64.h | 94 + tools/sdk/lwip2/include/netif/ppp/fsm.h | 175 + tools/sdk/lwip2/include/netif/ppp/ipcp.h | 126 + tools/sdk/lwip2/include/netif/ppp/ipv6cp.h | 183 + tools/sdk/lwip2/include/netif/ppp/lcp.h | 171 + tools/sdk/lwip2/include/netif/ppp/magic.h | 122 + tools/sdk/lwip2/include/netif/ppp/mppe.h | 173 + .../lwip2/include/netif/ppp/polarssl/arc4.h | 81 + .../lwip2/include/netif/ppp/polarssl/des.h | 92 + .../lwip2/include/netif/ppp/polarssl/md4.h | 97 + .../lwip2/include/netif/ppp/polarssl/md5.h | 96 + .../lwip2/include/netif/ppp/polarssl/sha1.h | 96 + tools/sdk/lwip2/include/netif/ppp/ppp.h | 690 ++++ tools/sdk/lwip2/include/netif/ppp/ppp_impl.h | 629 ++++ tools/sdk/lwip2/include/netif/ppp/ppp_opts.h | 593 ++++ tools/sdk/lwip2/include/netif/ppp/pppapi.h | 137 + tools/sdk/lwip2/include/netif/ppp/pppcrypt.h | 136 + tools/sdk/lwip2/include/netif/ppp/pppdebug.h | 80 + tools/sdk/lwip2/include/netif/ppp/pppoe.h | 179 + tools/sdk/lwip2/include/netif/ppp/pppol2tp.h | 201 ++ tools/sdk/lwip2/include/netif/ppp/pppos.h | 118 + tools/sdk/lwip2/include/netif/ppp/upap.h | 123 + tools/sdk/lwip2/include/netif/ppp/vj.h | 161 + tools/sdk/lwip2/include/netif/slipif.h | 87 + tools/sdk/lwip2/include/posix/errno.h | 33 + tools/sdk/lwip2/include/posix/netdb.h | 33 + tools/sdk/lwip2/include/posix/sys/socket.h | 33 + 137 files changed, 26848 insertions(+) create mode 100644 tools/sdk/lib/liblwip2.a create mode 100644 tools/sdk/lwip2/include/README.md create mode 100644 tools/sdk/lwip2/include/arch/cc.h create mode 100644 tools/sdk/lwip2/include/arch/sys_arch.h create mode 100644 tools/sdk/lwip2/include/espconn.h create mode 100644 tools/sdk/lwip2/include/gluedebug.h create mode 100644 tools/sdk/lwip2/include/lwip-err-t.h create mode 100644 tools/sdk/lwip2/include/lwip-git-hash.h create mode 100644 tools/sdk/lwip2/include/lwip/api.h create mode 100644 tools/sdk/lwip2/include/lwip/apps/FILES create mode 100644 tools/sdk/lwip2/include/lwip/apps/fs.h create mode 100644 tools/sdk/lwip2/include/lwip/apps/httpd.h create mode 100644 tools/sdk/lwip2/include/lwip/apps/httpd_opts.h create mode 100644 tools/sdk/lwip2/include/lwip/apps/lwiperf.h create mode 100644 tools/sdk/lwip2/include/lwip/apps/mdns.h create mode 100644 tools/sdk/lwip2/include/lwip/apps/mdns_opts.h create mode 100644 tools/sdk/lwip2/include/lwip/apps/mdns_priv.h create mode 100644 tools/sdk/lwip2/include/lwip/apps/mqtt.h create mode 100644 tools/sdk/lwip2/include/lwip/apps/mqtt_opts.h create mode 100644 tools/sdk/lwip2/include/lwip/apps/netbiosns.h create mode 100644 tools/sdk/lwip2/include/lwip/apps/netbiosns_opts.h create mode 100644 tools/sdk/lwip2/include/lwip/apps/snmp.h create mode 100644 tools/sdk/lwip2/include/lwip/apps/snmp_core.h create mode 100644 tools/sdk/lwip2/include/lwip/apps/snmp_mib2.h create mode 100644 tools/sdk/lwip2/include/lwip/apps/snmp_opts.h create mode 100644 tools/sdk/lwip2/include/lwip/apps/snmp_scalar.h create mode 100644 tools/sdk/lwip2/include/lwip/apps/snmp_table.h create mode 100644 tools/sdk/lwip2/include/lwip/apps/snmp_threadsync.h create mode 100644 tools/sdk/lwip2/include/lwip/apps/snmpv3.h create mode 100644 tools/sdk/lwip2/include/lwip/apps/sntp.h create mode 100644 tools/sdk/lwip2/include/lwip/apps/sntp_opts.h create mode 100644 tools/sdk/lwip2/include/lwip/apps/tftp_opts.h create mode 100644 tools/sdk/lwip2/include/lwip/apps/tftp_server.h create mode 100644 tools/sdk/lwip2/include/lwip/arch.h create mode 100644 tools/sdk/lwip2/include/lwip/autoip.h create mode 100644 tools/sdk/lwip2/include/lwip/debug.h create mode 100644 tools/sdk/lwip2/include/lwip/def.h create mode 100644 tools/sdk/lwip2/include/lwip/dhcp.h create mode 100644 tools/sdk/lwip2/include/lwip/dhcp6.h create mode 100644 tools/sdk/lwip2/include/lwip/dns.h create mode 100644 tools/sdk/lwip2/include/lwip/err.h create mode 100644 tools/sdk/lwip2/include/lwip/errno.h create mode 100644 tools/sdk/lwip2/include/lwip/etharp.h create mode 100644 tools/sdk/lwip2/include/lwip/ethip6.h create mode 100644 tools/sdk/lwip2/include/lwip/icmp.h create mode 100644 tools/sdk/lwip2/include/lwip/icmp6.h create mode 100644 tools/sdk/lwip2/include/lwip/igmp.h create mode 100644 tools/sdk/lwip2/include/lwip/inet.h create mode 100644 tools/sdk/lwip2/include/lwip/inet_chksum.h create mode 100644 tools/sdk/lwip2/include/lwip/init.h create mode 100644 tools/sdk/lwip2/include/lwip/ip.h create mode 100644 tools/sdk/lwip2/include/lwip/ip4.h create mode 100644 tools/sdk/lwip2/include/lwip/ip4_addr.h create mode 100644 tools/sdk/lwip2/include/lwip/ip4_frag.h create mode 100644 tools/sdk/lwip2/include/lwip/ip6.h create mode 100644 tools/sdk/lwip2/include/lwip/ip6_addr.h create mode 100644 tools/sdk/lwip2/include/lwip/ip6_frag.h create mode 100644 tools/sdk/lwip2/include/lwip/ip_addr.h create mode 100644 tools/sdk/lwip2/include/lwip/mem.h create mode 100644 tools/sdk/lwip2/include/lwip/memp.h create mode 100644 tools/sdk/lwip2/include/lwip/mld6.h create mode 100644 tools/sdk/lwip2/include/lwip/nd6.h create mode 100644 tools/sdk/lwip2/include/lwip/netbuf.h create mode 100644 tools/sdk/lwip2/include/lwip/netdb.h create mode 100644 tools/sdk/lwip2/include/lwip/netif.h create mode 100644 tools/sdk/lwip2/include/lwip/netifapi.h create mode 100644 tools/sdk/lwip2/include/lwip/opt.h create mode 100644 tools/sdk/lwip2/include/lwip/pbuf.h create mode 100644 tools/sdk/lwip2/include/lwip/priv/api_msg.h create mode 100644 tools/sdk/lwip2/include/lwip/priv/memp_priv.h create mode 100644 tools/sdk/lwip2/include/lwip/priv/memp_std.h create mode 100644 tools/sdk/lwip2/include/lwip/priv/nd6_priv.h create mode 100644 tools/sdk/lwip2/include/lwip/priv/tcp_priv.h create mode 100644 tools/sdk/lwip2/include/lwip/priv/tcpip_priv.h create mode 100644 tools/sdk/lwip2/include/lwip/prot/autoip.h create mode 100644 tools/sdk/lwip2/include/lwip/prot/dhcp.h create mode 100644 tools/sdk/lwip2/include/lwip/prot/dns.h create mode 100644 tools/sdk/lwip2/include/lwip/prot/etharp.h create mode 100644 tools/sdk/lwip2/include/lwip/prot/ethernet.h create mode 100644 tools/sdk/lwip2/include/lwip/prot/icmp.h create mode 100644 tools/sdk/lwip2/include/lwip/prot/icmp6.h create mode 100644 tools/sdk/lwip2/include/lwip/prot/igmp.h create mode 100644 tools/sdk/lwip2/include/lwip/prot/ip.h create mode 100644 tools/sdk/lwip2/include/lwip/prot/ip4.h create mode 100644 tools/sdk/lwip2/include/lwip/prot/ip6.h create mode 100644 tools/sdk/lwip2/include/lwip/prot/mld6.h create mode 100644 tools/sdk/lwip2/include/lwip/prot/nd6.h create mode 100644 tools/sdk/lwip2/include/lwip/prot/tcp.h create mode 100644 tools/sdk/lwip2/include/lwip/prot/udp.h create mode 100644 tools/sdk/lwip2/include/lwip/raw.h create mode 100644 tools/sdk/lwip2/include/lwip/sio.h create mode 100644 tools/sdk/lwip2/include/lwip/snmp.h create mode 100644 tools/sdk/lwip2/include/lwip/sockets.h create mode 100644 tools/sdk/lwip2/include/lwip/stats.h create mode 100644 tools/sdk/lwip2/include/lwip/sys.h create mode 100644 tools/sdk/lwip2/include/lwip/tcp.h create mode 100644 tools/sdk/lwip2/include/lwip/tcpip.h create mode 100644 tools/sdk/lwip2/include/lwip/timeouts.h create mode 100644 tools/sdk/lwip2/include/lwip/udp.h create mode 100644 tools/sdk/lwip2/include/lwipopts.h create mode 100644 tools/sdk/lwip2/include/netif/etharp.h create mode 100644 tools/sdk/lwip2/include/netif/ethernet.h create mode 100644 tools/sdk/lwip2/include/netif/lowpan6.h create mode 100644 tools/sdk/lwip2/include/netif/lowpan6_opts.h create mode 100644 tools/sdk/lwip2/include/netif/ppp/ccp.h create mode 100644 tools/sdk/lwip2/include/netif/ppp/chap-md5.h create mode 100644 tools/sdk/lwip2/include/netif/ppp/chap-new.h create mode 100644 tools/sdk/lwip2/include/netif/ppp/chap_ms.h create mode 100644 tools/sdk/lwip2/include/netif/ppp/eap.h create mode 100644 tools/sdk/lwip2/include/netif/ppp/ecp.h create mode 100644 tools/sdk/lwip2/include/netif/ppp/eui64.h create mode 100644 tools/sdk/lwip2/include/netif/ppp/fsm.h create mode 100644 tools/sdk/lwip2/include/netif/ppp/ipcp.h create mode 100644 tools/sdk/lwip2/include/netif/ppp/ipv6cp.h create mode 100644 tools/sdk/lwip2/include/netif/ppp/lcp.h create mode 100644 tools/sdk/lwip2/include/netif/ppp/magic.h create mode 100644 tools/sdk/lwip2/include/netif/ppp/mppe.h create mode 100644 tools/sdk/lwip2/include/netif/ppp/polarssl/arc4.h create mode 100644 tools/sdk/lwip2/include/netif/ppp/polarssl/des.h create mode 100644 tools/sdk/lwip2/include/netif/ppp/polarssl/md4.h create mode 100644 tools/sdk/lwip2/include/netif/ppp/polarssl/md5.h create mode 100644 tools/sdk/lwip2/include/netif/ppp/polarssl/sha1.h create mode 100644 tools/sdk/lwip2/include/netif/ppp/ppp.h create mode 100644 tools/sdk/lwip2/include/netif/ppp/ppp_impl.h create mode 100644 tools/sdk/lwip2/include/netif/ppp/ppp_opts.h create mode 100644 tools/sdk/lwip2/include/netif/ppp/pppapi.h create mode 100644 tools/sdk/lwip2/include/netif/ppp/pppcrypt.h create mode 100644 tools/sdk/lwip2/include/netif/ppp/pppdebug.h create mode 100644 tools/sdk/lwip2/include/netif/ppp/pppoe.h create mode 100644 tools/sdk/lwip2/include/netif/ppp/pppol2tp.h create mode 100644 tools/sdk/lwip2/include/netif/ppp/pppos.h create mode 100644 tools/sdk/lwip2/include/netif/ppp/upap.h create mode 100644 tools/sdk/lwip2/include/netif/ppp/vj.h create mode 100644 tools/sdk/lwip2/include/netif/slipif.h create mode 100644 tools/sdk/lwip2/include/posix/errno.h create mode 100644 tools/sdk/lwip2/include/posix/netdb.h create mode 100644 tools/sdk/lwip2/include/posix/sys/socket.h diff --git a/tools/sdk/lib/liblwip2.a b/tools/sdk/lib/liblwip2.a new file mode 100644 index 0000000000000000000000000000000000000000..4c3ef868b9334ff6d0f71c2c03ae904bc3a3170e GIT binary patch literal 1039116 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�t)UY68 z?j9d}%58K7%6fMK3i`UZb0IhQ$2SOagAb!$b|-d;bHga=*YDJ@ z5Z3FW%Z1$V{Yir$x6z$2_WYA+mRmO{i*oC~*GR;<;XAGdmE7=6j$f{5SPlbpt_c2Si=4wtQWvNG z-LN_w?Ju&Hf3#&L!iEFzYqzSvr+WzN6%uukXC&RP0>v-F2(nWOw+ z(C?MvJ#-A%=gW*3SjHooZP8Lnb-umL*7FXbR99w;wM?tmWuKP!P5r_2WBGVLOt0e1 zU#chdZ`d+5TdHpW{-xy@*xnbGzd~G^s%4N5p-EUCkSeledUC0raPuCR!1=ILPxf|e zw0uaaL!;%vscyEcODyRRN%gU1%2=vz9S3Nc{o%}9swc6-Y`qr4@j711zW&E*nOz`q zJf>x>pQYtNTE{;ODb#&>l2norYf|IJx2ag{p&dX6)ElG{;)hMb&%=r8J15<9cKEchUL1{@mlU8 zUKf_fq)yW^+oMgE%Ex}9mf8P4s-RMxe}Adv7()AMq<>cGsz%EbQ@3fE@}XO*^YQ(* zzIRxjl3J$a7|?k^%hgKxM<}JK^HQ&8t>+$#vK^;bs`K+tTBf{=?4>-JNTvn|K2rFo zHS(rrp|KBMoC+n*rdB_vOoJ;{FqP$4g)BN${oH8SXfhWGE4S$)R`2|VhVyuHngCDDt0AH;B~Dn#N+o zq=I3k=E5L#{-i86%%8;4l>ah^9_tc^QmDa;l%;LDj9i^6e2rFzd$gwY)|;n=?t zw@jP%ja9g0T3YXinJk<0B?~|IxNMmBi}lgrGUzs%-!C!6)PAv@$GPxW6TJnQM~FG6 zlCdYv&A0+%QM!M?FpiY##Dt9VBTU#$5oVmNFlLNtYs@&+&A6x1zQ){rafL$O?n)0d z9-(xIG3(Jor&j3+#(OJe94=R3xXb0v79OT_sPRap+`%EQQyR)Ft`P5{h@7!AlwXWK zA+2GN&_)p*0-P~24_r;9&)NZ=-X{j z*p?j^txBb*^P7A%&3iNg*C{Z%++D->DP`Z_sY{D9*s;{{5)Iv!}u zvk;DbTE~cRup-++24^Ja92Aa=e=0TrY}k4;rOys3Y?G2#T>V}#^n38 z@e-w>4yE&`_+cksVaztUKgJH>?~3q7rSBQ9SNegIa~+A!yGpsngpXDl`i_|Pf2he} zuIteGm(tMQ#QTYrq|%q^N8wmSbdbRrlZRs@;m4Bk90HxElyVmUvtOajh&e_qBVV92 z)cH(-!qbY#k--_0(W?u9?xB863w1VJba~-$cK>Bw_Xq-cxDV7cu1tWiXpt$-~$sX8X^XoM)*2biA{c z(WksCjhX3#dsO7i=y9O&;Yyjw136{DUl?Y;xkrT8D1FGu-!`V6-ZyTMt9LHO%(C%~ z@efMNw2U2Q+30A@%pF~fiD%?A@MlG~iww?~{AH66cFagX68n-Kc+}HpKBc zz<8ii{!=RQm0E(4Vg#g-=Y549=MROQ+8>7Rt7Z zQl78Cv{n3VB6l|CpM|mxIWx;t%WnE6wxnx-sAHTl`2i-Uz0>Z=%gi;sq?hIbLE&VR zBZD(0uhDXPCK{SW!*r0raV)*Wg;JiW!05bWj7~o-$7|77 zOpXkW=Lp6K@-j|*YRs%RwdA#O=2-ti2FG&JSIPT<@(o1a>Sq^|BZFhTwKF-h@PzTX zBB`@>(kmBtSITjPsW+V->g9VF(@xMsXE&vUxZQol$O&-V?f@}z#>;~o4{@9)j&(KC z7%S5ZBnphJar`fUZTt`0nuUgq)s+b|#FvX%f4A{6 zrHhQ0DqZ5_tV18$uNkw=b;ds_eczaJeeUEu;3MyCO7T~N>C-KZ*{3$fJag@0%kZ+l85u1I8WBd6}mjM?t4#vI>{#>}9^GWzY69&5~O7aUjQBb1IcX4a%$ zvX#C=KMLbbjttJ2yhh7W=OWWV21lKK=oIKj;YQOz24^Ivoo5uw+a~wN!c@AF-{kuO zcDTMtMQ=Z<6$QLQS#u$6^9p7tA zz5|UHDjjM(L1~d<9G_1xIWjno&+I4LnyIvfVr)O`8**fDY(H0-{6SL1^ga4f2;;Ey zk--_0Q?1xRpZ$UNQ%Xo1v=Wzh45H*1v2zNgipZ%GIAd~Dkyk4X^?aK^p|c`#WN^mh zeUW!c&Se}wxK8Qujzim)oMXF-$@f>fr!mK$?L|An`nDa8o$?ak*tW?Zw-t_&*&k$b zw#B~1J{a1VbdbTZ4~FAtZ7J;UEUi=sc{w;1;(0T)VJbi&v{mts;wg&dV)D%}o~Jal zG0ATh-{9n-y-EI*WD88r_J3^Y2d zkR7EM$K|BA_x!BHPQ%JZ?(c8c+Qy58i-;CMc*LT9Fa6h2cVFETjR$!3#t zObKarNFj{vG+5(|$yrV>T>9l?~15cBRXMoxfZUUlgpFIAeS z81K7<_0MOD#pQb;N&L8AbSo8M#=KxhytlZU$>A^_N=|w9H92j(Kr!xnKa(SaoLAVN1y&O z$e3~sH>SQv8dJuTj9ZH<6yr0=kz(v1gX1&FQ%qj0eCHd_P)hmGpQQ9EtQRmnN0gF(NEbL?0QPk(_<6R*W_miqSy^N1KaH zj?G@;X!CKCBZH&O8g#6jj6v8$21lDOm>iq$8*f(niDQlvdDkiZ);KMFnoF#!?@f*j zj&)Tlj%8q0PV69qV;M3gpQLmk`VZ2Di9~qo6IqTBD;a4)n@*V*LXH1TykxtK_ z>*S%+H<9xj`(}Z-T$RcCV4sS$kbWcq+G6=W4V*D~OOtc#c6Hp*m?46^@!pMN@1N7g z`@T>%26Ba^isf{41&$3oU-j{mF}mS8T=FW(dn%$s9rrV4pF;nVyiT&vzrc<1kK|ysgQZt&ii4evwkS z$Oq>5bFUR`?rY4k?QhI+Kiv2jr7WXARB4sUk)EL+g)>c#49?6zYGc}k3IEb`7}MZ* z{Y;yS&o^kJv2Bwpw)xO67?c!xDVB@TJ;WFrLyb>XT4_8+X?w?^AKCdgoF8Qe8Jv+E zo1x#C4&9z@A%mk%f0JYXAjhHIO8-R3CL$*e>tlzE=h zACPdUE90PV9Q2LDz8Hu8V%&=D8i)35T;b&H99KCOrpg93)D?{FU|&oK_M0S({W3A@ zD`4rgQ%X#mez4C@D0ERQ6SE)P9jhvXdes2_z9ie<(l zVd;-jN{sq-Fax>5Sj93iWj@34MB|;5o^QOf(iyO9&QwZ_HfO=?h{9~eGBI^C*YP~# zU6tNxyqnTRuxu_?N{lv_z{UDecv7)UoTv1Uj#n7xD_sT4&T6H^XlD&fWh$&yEHi!w zmi{`W#Hha>ZlNEA4T@!A?M~`b$D55Y^}R92i04AsEKo{}HW`o7C@8c*N36pd#!{(P85tFQna<9lK0FH}m5`io#1s={J)jF-UDe^Mzi>Mw)o2nx&5Fn zf2C4l)L#YjkU(KII>u{Y>918vjQa1ubP$Dg=!j{1|8~65n6~$&F-_|SST=b-LyR`_ zU>g-%7%4)KqTTx(1_JjA%U z7#~?|j!;UBHb=shQcxI$j<{Al+VMDJPBBwp*_o=8813Lwn{F!wg&F9G^Td}s=G_l+ z+V)Mb?95Y2jCSV3?XaS@gpQbFai8Nw#vF?!uD(|}x4g&2ChwPs(PlZ^Q3?vJ&=Ir0 zyE*0^6LR*K_rlnzR!WR^dcmErqWdd!#O&{Wjt3gEze9}K-x08Ej#NsFHb=porJzuU zj<}2XRLA3u_mZ4>nb7Gjo&n3|Or^wVa~8a(6clEoBhC}gbv)0QcCrALoqLrMqn(8? zg;7|9ju<(W*+=GK!OjS!#As(EZ1=Fttx_gdk{a!JoH2GL!UHvCC?!Ta zQ{i4xP?#nz6Vp~_zysA@loF%kx$2qQZe7fU_j?Z^|rQ;hM|Jw0F$G>;Xv!hs^zc_x~@!uT3?|6%2 zo?S#cc{-0rE_B?&G0%UZPHV@!Q;zZ~$K4$Fa?HEusDH3yd|aZOcaf1#b^Hs*=Q!q@ zpr}9H@nw#$avWypw>H3YhnV+Qj_-2(faBjf{=MU+j=4^YHpBIpZ7W=N8LxLbTt`KH zu9qTrblk&nmzQpmhj_-5)sN?q>f8uzH z<0cx2WBE%R@8P(M<35fLc0Am1o#P3Pf9d#2$2U2?%kjgG|KNC~<2M}t%kh64|KPZp zPO5Q#nX@QzTgS{j6y^Il4s#9Jv1b0CsB@*`FrSX;yy@iMIL^@pLd@ITaVy8|9CvnH z?RX!@{TvT)Jjn6kjz>5?-f^Ad(;ZKCe6ize96#dt503xrILy0Z^%LeyG5*Bq{N%V$ z7e2ABx;XCR_%O$(I%fWhn0LD4s~q3u__vOiJAT>mTaG_)%m;mOTeXgd!0K;=BgFCf z-YLirN#y4^W`4J5=Nj1Z&UNznuD(dksciiCFPC~|$cFLEox0q~HZk~-AMk8twioqU|*2~KCKlTUZ@Sx$Z}tVp=U z@k8*CME*F;#iqhj;`oelHF7KS8}N`sXPuL8a{QIk;o>#sZQ*!F*zB~16$zD&+lwi~ z0?E4}H~l_vtV39laFpX;IKB|JyjQ^X%=2n-eCD|Tx!JtW=`VKj$6(9*rqlT+yhBok ze~aVu&+n0&O{N}*WyruLZvhWZ^6uz#+B)tG+w;p*n+-siP}`$mkP%nVID>)>?w}VREImA<6&+J z6;49O_NtozuAuwmMwkAddv->^M*{Rn+~?z#oJ z+5ge$&`#0ed0L@3>g)iUomP%39e07P4fKTV*=%odd^UR+a@+1vPX9zFALHZ`oP3g# zPj~W5o%~uS|Fz@0oz8=>mF;0MWqUyT`-IbZ4z_as+3Bx!{EnEsIl8ammUAp@mG$UXiSRbX$hPC-QWsUxI(44tRi_f)y3)bhOG>TI35a1pD;{ZR*|&T zmC0Gu1suxDUQ$cn`xYj+bxEzJUcu2?y%); zBPQ>CGPS4E-^c0qbNaQW-(Kx)u+tym^iOj7V@&@L=}&g@^PT*1C%+1|_HYwyb@*$? zcRQVjoO}sv`}Kwid@n**bIuFFWd%%|@b=%&_`@ypk`2Z&$4qH8+1h-9e#)#wl zk*UaSU#2^qxp2Eg|7P^Xx^zh0>-2x?_;JV2I9>spot0wjRLjmAPUjzvKXkmw@mH|f z$=CTUa%;z3VcXvtxP4Ooe&YE4iAOF@?HyfO7hMX$M-%DAh+@?a{5m=`7$T}vy-oa&E^}9-*fsOz@3xr zek_jfhWH2}Znp_+7Ot$q#Wn6gHc~#MtDr@Mz?=FLh4;RHr}D z>6{Pmm6Yv5aeS9|h0~b}TiNb%e81Cq)X5)r@@Jj=1=zN=+Ub1c_$$Xby1tJ4vV-G} zj(a*j!0}MW$HLu{eLO)N-!q=(bk2coA1`ryHEemW6O;EenY!J{?{M-5kei*wj+Z)q z8aA6RJAO@!{TF5bpHBY+r}MGX`O@k9;JAqzLM%hEW9}#7c6WE&-SI%j$2vaK@pQ*? z9N**k8Q9w4OK^{*{$CNtcd~Ce`NvNGE4XK(|1J9BJT2zwnmXFt0k(Q>1Dk$Nr?WrY zE3q>`9N)c;L~eP{g!?8s6Jaa!h44O!{9$ZLPX3^iKj!35Ir;NW z{)Xef!&ZikPX8OYcT%?R#qoV^iEb8Sd0N7@FO^Q-!O6Qj`94nG-^q`3JlgSTPX8Py zKM%HRhKrrf)lTPnC%@gv?}Tl?7Q<#|sncKK^w&83wPNaFsIIa9>GU@`{V$yU_l|ei zy!*8iQ{|l$xi1Y*xJcuPJW$}-{|CbIQczJ{;-q(9=7fN z+3{MZ|32I&DcgtQ_-_4sCTC)_`g4|4JmaBU(#%gKKUACSmr zI{6%UzeIkslivmROXT-E`R^P*?f515mPG$mCx08hHIc7#@{RCCiTraX{}Hx(oSX`= z)k86C*DYmEz6U%n6+$m3uZ1s2s>wBt37w>oZ7*-+*Vj=MP? z;<(OnN+G^GU~G-7Tc3K?T?>4ytm^4jt_P`-0`uF$HN8sQJAP0`FzJ0 zI=vW5+6+D$rhkf) z^UXrkIm_|6j`?;y>dbIF)A5at`L-qM-{JUf$B#OG%<&%`KkGR7&|3L}&xY||ozCAJ zzvuXU$6q-9+VPK$)A&D_{T46}Hx$Yp;}aX@dpKsk*eGYtlgRxX*E+@zHtGy>-ap!zjVypCec3ru95L~jXcNkt&V@?_-@DdI}U!WRzJb7)p&)|S?M_VpO_AQ zt+5P$cg&o$QT}ho!AHgN;@28=nBOGw4~|p04f1@)8ONoLnTI9XY45m`aeSHMD;;0w_y))K!g@bJSm^i>$G>;{N5{`PUg;Pg z)M)b`j{oKOGsj;z-s(74C$MN|S6I*Y341v1;JCBn?vD3%e2C*Aj*oJDjAML3<95e8 zz7Q@+%5$;f>)_HveuLxN90z|S)4A8l@$-y%pMuL0J5M`)-ZB21QD?Pdd^@B3ea9a< z{u$FVzRmFh$M-r8|Buni^N5o_?)WLk&pLkI@hZow z9S5H-v;V%62mdaU|HsL{cKn^=bkm0V4?bX)x5&v`IBw;*wd1yqJ38*>xQFB5KW5w7 z&&dZm9_08~$0s>uvrCpjMD_)N!VIX=(vFCAa%_zK6@I-cuzf#Z7}^Z)GP__NsY6ORAj_&LWfI1WC3 zw!eRO@{b*V<~U#XKykawa}#+l$2}bfUp}*cu#+F=_(;d29iQrWisPw{XE~nj_*Za+ z24{sk9f$wxRuROh2c4Y%yOuWja>v2<&*Xn`^4A@|>3D%{Ab5+ zIeypie;fyYPCItFx*v`8lkXUR&L}T+j1Om&S2^CxaZkqw!R?cFGT8Aj$0Hn{;P_<6 zr#U{;@i~sqb$q4cYaHL;IQV~B*?#ThcR60@c#-2jIDW?QpB?|j@!uW)!||tZhopW! zcf7^%4~{ds7mWHlINlxZl-OzGxRc|qj(a(-aeRQ|105gg_;AN{j>kFIPT$iAIJMU9^g3m>)N&sbMm7dALn?SEGhyw>$ogvS8Sa{t=M=|hIzG$sxsESze2wGl9pB>kcE^hxFLwNd z<3Bil$?+?W--Y)|%KuNt8ys(R{H5b>95=(acCW-vbH}Y6S2(V69Q>9oZ(k=r!0{oD zhd2&C%$D~UCqET7UyCywPjo!R@r8~rc0AYd&5q|gUf}ov#}7IFo#V$H|IzWYj#oNf z<@m3T|K|7~j{oKOBgdaQ-t2gbH&~b_59UXUs%?D;r$2}bH<9HBkJ}1G)+jzK>AM5xu$HB+j^v`kf za~)slnEy2&w{??a{YX!@yCuocl?#(d_8NA zb~27j9k+D6o8wByRgSwj?&-L<_eLj?Z#@uHy?F&u~1`@imUG zcYKTE+Z``*yx8#*j{o5JCC9;E-S*`TCx6TF$BsX9{I%on9P@2cJYG#4H+Nj(xRvA9 zj@vr!=(xAzzK(-$yzR@uPJXoG;~dvH9_x6reUyQsO{a%TjIbovzZSX;|>jZp|qHk?2 z`ZjhAL@usY_Cd&N5JMjy*z$gPi$KrRmTAl2B9SdL7cMrJ=Fb8KS!p&3Q4aNN!@ zWr{lNUSx_Gxu0X|E?ub~g`tX(hdCbMxDK}GlVcr^b3EShM8{Jc&w#BR&U8G>@odNQ zV5|T6ju$w-*YRS^b zaFKo#HY!Hm1Z#{XY*viC1-9|_2gfPeRSO9ef?|1=hQpyb!kWc9G-7u#LA%96t$nNy@p*@p9P4 z+ZB#i!ZzNna=aS0@pg^lwXlu1?>Jru+jzU)@dmh8Ql5>DH^DaEZg#u{w*LNu;}kw` zHHn=($6>B28*ht{8wbBo>(@_V$NKWl=vbc(zKeE^v@^b2)=%5yiLGx2KP&5xE09~i z+e@}%Upo)Bz7~9GtbeUXZhh)|*!ofMOR>JQcT>r&j~oSCA2}PgelZWWzVH}q?Z4Q) zqaUMvN>?QH6W*^?Cfr5)6x;J?*xK;jaQj3jJbUkuaCo+C?Q<`lXIh(F09!i@&jVxI zQ{BY&7M|Bx8}rZBZd9GcwzP}tDYl;jVQVwvVQVK>!PYib!`2>VsxD(2$aUAxbvnMK zs$Z)5G-IlCysca1B=`1c~O5`SdO;rNenwfHMz zy28DA)V-*|=?pI&q> z7yrk2mKdL2wpmff%1&_&#xS;|Ikh#*4)5U^Oa+4(6jZYR|WIRSZ z)A%&;)yCt+bBrg7Z!xBB=NnHG-)(%U7++tuOC3IJJX^ffc&_+Q#c!_ZxQ;GuJD58CQR2OkaM|xUYDbF>UNsxJ5EH zzG2MR__lFN@js0jbMOa7U!RSoJ~gJDe`(xS{H<{Z@m6Ene3K?gUfOxaxRiZSIp)0nzF z%b2>o1eOuDb)_+fp7|A#b4+hErVjA|M$WeGG^XC}G3Gep>&x?ERa0u2F=c+vnD(~P zSi7Hk-I(LD))@Qm81E{^r?-?wrSPTWrfQ6(oa_|v-HnXzE}SDdKDwnCSLo!pt1&vY zFb!3Kc^xAkYK+c_Fa=XM#qsIJ=rG4)sa5uooc0GnKZe)CMVGReV z<*+J&KKp_(#{!>QN#&Y)l*2WZYBywQ)Z&^G0I-AaRZg z3)7yP8V?ii4C`b)NQ^%%j81!FboMkpO5ELegt)iy@nYtgB=1S$1C7rR4>lezKEjwj zaxp;!{mE!Y_uN7ZnJV(qtmXzTJG5)mhJn@ajw~KExo-e-B z_-^ri#t(=eGUi;se3;nztr*{0c!~Ir#!ra%p5`ejrk7m5aYwd`1F!@n0UA`|4ZmNW9C#o*?5%rG~==2@y1-U zPcmkHWqf_Hd5-uZW3JOLH|9DWzh88iQ~6foYs7aLUnjoTnEP-1e$k&NUTn;@{Nu*l zf8!5~&XeNjjQKuqrSS{mSBzg4uQ6UN{<|^X>a8<=Q~aSZ_s5?Z|4Y2tc)j>LW3KB{ z&5|;FF2+xo^6(8`k?~LBQsZ0=Os$M}5btix|0r)~%y)a8jk}7gjjP4@3}e5ixSuiC z`vZ*mU*&_04-g-2%(edrFs@g!re_oo_95MN|`u9*2w zDI3@ObBwv(zr~nu`{oUpurc5BEiqmwe#)5nq?a2%EPlcGQ8B*9 z*yMj);BO2w=kz~}xj$HM%(s9a8}t9tzcS`t;RoZj;+(?7&fDSwW4;B%4;lOa6qg%w z53!3e{|~*wnEQs##@~s18S`D>{>DFv2O77~3F%N{zW*C$%zeW##@sjHhfEpv5>J3D zl4}h7jbW}aE->aAgLz+(mx-@4=9GPtG3T;7jN6ERV_YTvy>X3rsd26N8RJ3X=Z%Mm znGcq29WH*&_!#luj5!D4V~kFn_v=>e@k^(ghAY7&PWQ$o&@bVdCA4 z$BFSbMm|B@+4ur+wefZ0zQ(tR@i#{Q4)GA<`@}~ZKPav--k{A20si_(XAzE}D>YjwmobU0iI;vz&5c zzT4i#c(%C0c&@me@onPXaNFeic0XgCR#W&DBUcwq4K`L$Qb!mUi;p(u67e|WO7VEO zU2=^#$(X({)tKwLi;T&OUorah1?IVhJB#NSSBvp0M&3hwyYar_-@@&a{)k^O++6ad z#x2Cp7}E!zH|Em!FUGnQOuc5jyZCR$?90E5RTZg?#vR088ut?8OU!l$h_@OK6gN>p zkRKw(ml&q+v^3@(3SVO6TsL+!K2_Y+_)Kw6FXFOB9()dd8E5=ue*BD_c z`@)!mUopH$j9)SQh?qHkOFJg*c_-si$#*lRZrd8uZaW&&Zuf;dCGE4;nDfQK#+)yP z8guV+lreo|r137|lZ)pM~U$(Chy7O ze;SVwe`q{b%v{9i{6hSt@!8^Ujn5J1se;j&A}%(bCN4Lo{p@Z`n`v)+op?{<1>)|; z_lbKOKOo-E_$l#$#>>R`8?)V~#YY(bNqn^Ni{cZEUlETsUL!u;_)YNy_pe%8fgTJHmS<{jRIA4s(im zl95w}KE~x@e2dA4w`@i57mR~h+H;>E`FLHv!8pCVpne46+<<1@tg z8>90J@hip?#A}QviT`eVsd%07RpJkfuMuxFo-6*s_*Y_ljIn=*_$TB0#d#%(e6g50 znbG;ZxP>u&VJG7k#Jd^4C~j-~x)|SM^1dNverEV@VtkL`x5Ryo*NOWZe;_`@_!IGA z#`KZl#@~vMH~wB+XPi#!{>wNc9&gO^fl0=##Z!&<5MN~6Mm*EFN_@33^Y`GNOqqL% zZ!xYB&o}NXzT0>|@j~NT@x#UkikBEO$Iny7gT%{?xmJ9^_;B$mW1cg-ZaiGP)|h7w z|1cgYUT=JY_+#Uf#G8yqi@!GJI`ao(t}}DgiP^_9#0AE@ODr}%Tg>xRbhs965BEsM z2mF~~#+L5J&BV-EjhwNiudz0nIvm!?g|TIXF?o+SCU2cFd6~Z&ee#|U_e##W(;Z)8 z%=my0bLl>b{o9Ro>6Thx%s6wuv6_BrkuiCHXUuv3Nn^$qe4DYkyLg3hrFf-rwHV*# zQVkmLKaKl{KQyite`Q~19J;6RSaEmb z)5Z8LqjQFMfHCJve3+46DL%sZTJh1wbHyhZ-y|Mwe5?3$;|1ag#`lOP8$Tq*pBeiP zi!V0*y_mVRkv}fRpBY{%o@>n5a;q`tS?1YBXNCA4<3EdkWBii%5#v?j$Ba4u;@eE# z*Tl~nzbF2)@p|#g#vh9RYW%qvKWFl85x-~LL~S0QXXHiV&y9J;_>FNZ@sGxgEzIMM zeh2Xm#*8gH8Z)-+YP^rQ(s*BS7vp~7eT)Z+nfDu;L&f+r!$*n_GiFQ}Zd@lm-gv6G z&iHciX~w+sA8$NIJjwWGG4q6D|90^-b8SXE}pBX+-{1@Xx#IG6CFaBmcLj11rF=FNqCola4e`feZ@i)d?bAE43 ze<{|*c&R!j<4?KcR>p;r6QW;S0nCp=3&rU3)(U1|QK(Ri{xjTbMV}eQg6K1&V%7W1 z)WT{jgh7hYzlHsbK3yZ>3jHY5DW<7dg>i~$Dpp~lV!BaCaNMoR4^lw=W_e7e!GfwwP zc%72y-?9N#yCQ5-jQ%ZKU>%njV*OLaky|-tx1+q;G1q5NKFIM1$90a!JD%!zCS0H& zg*l3m=R02Lc!}fXj#oKe>v+B6P!G1PADp}(-LTzq#}%+O)Gm&>E{Sr+i`Z7VhKS5N ziOAy|PjNiM@odNQ9N+7BvEyZqS2|wfc%9>oj<+}tK5twADERsMTIZm&&OjqS37>k@dn469j9^|@)p5dv?#Q4 z%(Lt$5C4~WheQWom*`K6e@kTk=W^sa$N02FIesjW@m-0Gze*g_@KK43UrOX9j+Z-L z<#?^*^^P~eB}w^za9ohrATM`Z;kb+A8d%p-gn^ESImTBc>V)~?On(Y;84*RAt8)wiACKq*xzcf%=S}Ar!aC%}8y#UtyKE^E^w{~3RxEH)rVjq8u z$YI_#ljC<08&^B-=h)9tHp0p49FKQA)$vTn_(H^O`8moKI=P>VY`K%; z{}A)y^AH(7hsgLgM8=;XazTCr`}x5toV<(U8pi`24|6=q@i@m*9M5n(+wnZdex5Er zH`g+!v(oVz$Lkz#bc_!`-1j`44+4NBhPfq`{*d=9du;gJ4fbSbL8cYd8ZuZYaR0*Im$OV=G}3W^S(GT z?}#JwUN~|W$2E?57aVnX{~LJ}+%`Ez;~YLKFPbr z@jAyF9dB`*r)!^>w}s=@j>8;KX1|w{*E$~RcqH5*DbHBP6CF=;9R7Ew>EGn!3mk`e znM~(NCtu-sHQX`T?mLb*INt0SC$e~-QslUmW8QT}oodJZ91n6l!f~Br-f2cVyvK|j z=0xh8l$rOH@m^`Z?u-kn7b--g(> z7CHHoj#t1vlJ>LO@jH$;z;?g9*)fhMQC82e zyo-s?LwNrZxwYdexNl;=7rcMMwQ&E0hr$OYJmriDr=ET8l*!%B-m8Mpeedc%d+$@z zyQW%PUG0DO*{4@UMUS4n`}7E!b%hrnH1yzfS~utx((;0BSkf~~#v0wbB~7&|)i-53 z5;G_*eRkcq-G9s}n)Kr6w~qX%f3tI{->;}$Q<2`Xb-5nM=CnL2Km9e>{fn*rzt}o5 zch%9I^13!@nobSMt8KHqDDS&AgNr`u@>ai2tq-|5=iuB_)sBZX>G({$OrO>4=HUxmRbJD&qUZ9eygsdux#7p&2dsNx%hu|B zmiH-r;p?ph=d2vP_Q(zWw{$OkwxanaSK?I4Zjn-z-)}8_c2iAGv+nP_-~HRIHMy&X zci*C9er{1&pPcSrZ*8;SyP~}GSCqd%c3L<)(MB{ZLph^!(?6hF`OVg{AcR-LJ_NpKtwHoh2n=zgE9B_qFe~HhZ+H`HOe`YjnXE zqw`zlvmzu#KWy}p)Wi9%hg zn!i^y*A%sRWNXVC(`nU|^l1>)J(gD$4Js|l>D?=*y4`ZBI@a5FW@3Z(oly62l5Vz+ zG&WgG#r3)rNNrWfO{J&t;-SjcYsd)yqc;yb#T7g%OI_b25B1qO*XCZAHzOUsP1ACC zPR}VOuc>~DTkyF~N~`PF(>D9CKG87!sb-Nn`l@|aaS{~oQ# zxv{@i6l~B>vtQ^(+k98Qg|||Urakkep5Zf%roA3!Z7Tmo{p9st3ihRl`%MuR?kK&2 zCjD`6%JABL6zR@(c#@=YXk9YbxqSRP!>g=;-9npC>LT z8h`3psr)A5oExtik^NJr(t|rC2Fl$=eSvvW}*Q-PY#T_MSRy<5x zn9BdHtTwAj$=VL1$(8v9p54W}OPngE!KaH~!g4Bqx)urt&d}N>c~|JS1qX!BHN(Mb z76_46-zRC|2$@(=xN^L@vqDot2-VNMEzvY?f?93|cw93rI<|?Xgm&}zadf}^Z>rlOguT@Ha z_sqHIY(RgH%%$WFT#-4Aa(;xovS`YLNvXn*IsWZ3Jk2ls6t2pgqrE8ntflO9$=rzj z|G?cco3*xZ6FSuy{_9WSm-mQ!6-}6|{rZYB?2|bf`&-bd$(+n~zlHl1O&*;p{0{Zn zqRHnO4k(&5<78XX7yx*`evV_kh3o~KOsFE)*P!tT*mGIECuz6S*Q}Qee zJA{R?B|Hi&ED8VM?6eZTbyF8)cgK}HiM5^6d`C3CgfEs0cL@s=K@E7S@Dam{Y>zzruaP!c8Ug;KIIPVP47EtT`Z5;{1{k80a4seqBN%E*uyZ z?odZ%)v)trx=G%2{f1^w>0GmCH=2dEpU->o!jtX~>Qq@!r<6{e%1Pz(UsnpxpJyU?JS%KwtxJnyTZ#PkFO?0uq;Z14Bf-AsCAehoW57vuS#VEa}Y$PRC)KzW6? zU#OMEg|d(;4*zPR_)ZCOidU!>a*KI5o>$CN3r&izl)P#2Z?)b0;#&O{6hAL{vtnK% z7OKW%xuWnfj#bjDpK!f8u=VOE*t+%Vz}Bk+Td!V<8SB+cU9Vp1di7H5Sg&5n&h3)n z{eIye8K+vS?%1=!$0ce}w1t)y28^O_!Bo-2RMB@FoxCvW7JZL_f)YmBq9)-87nba< z{6(4cD-=cMN|hEKELnN;njo7z>6BFSKH->Up3%zY`@%VyU&w6pzVy4i%;Bn)=KbJ; z49Bwhe&`exoqyKYRP+7e;>?e-+57;wMdl#=Hm`+CwaM^pU6EF&SH;Vu^!y10sZ`lg zZ7;nFyM!`MVd+&gW87=XITxkFXn3_2cg)d-)30*!!eOQ56kAxs!dYjZpGvRB&=;uU zk)JH$_pwt~$wp=5;HPc2N*|?r#GPv-Vy^U5>3Q0>^o`|0&gSX)cS&iNS|N|eTct;& zt6QaqH_2@!iSp(Y=!$XImnrvjL|mt(=YOg^NpYuhm~l+oxt(CTwy?_p!GE_^`WGtZ z5o~c`k)F>NQ7z9%r60Xiiz6sL+rU5!kqtw zR_zgvRY{tIb(3O6I9MfVw)BdYE0yZyU7EvHrk31Bhbvj?r=?v6YVAx_PI5F-yFbK1 z=o4OCo=(R3w-(BOv7@lRVx@LImF^de@gY}bIKKOZk!~u>p)mW0!d%0~LSYUFh2aCN z%H1$u8#)9ZRkaDtrGLo(nwEE_fl!G%9WS6<{ELF5Z0*KMlyi}OcF$8W(&vPV;Bckq zKOwE1X*uBlv~S8*rU$D<5^{-~p8tt-lJZ_0)~siH?P8t|?{oAgQcF#A_~e`PqcD9A zE!hOG3e)FO4T+#52c?_JSVhU2q&j^}jzbQRBvIIHcVXvKWv*yIn(KMYEg3`Y;}A8zt%X#bue?;$4f6-l-(b ze{;`ir;nEQmq??mq1un`3iy<%2?@S!O?OQ3Z@lwcYAD_}(>KTpc1(BNnU}lGngsv1 z!m@O3aVEoRr22#->ek3qkroS*tSmOqOE;(%S4p*XbDawE8kuOp76zALt;DP~8C*v8 z(r)Pkc23N9+_@xO+O)RStph?~%9_+~Hb=Wxu0`7{i#zsew6>)d-P)b5x-_jS>K?Y( z>gr3=shn1G2dJU!tQ9F%sNF{$jUnAsT6QU`2(7c_wbO&b!T~$yNTqW_0S?%?pPIv-_2yLtgUkAb1JI>g$_|Zo523!!sTWBPK{uZfL2v>i zO{b0`IWyqNBvTagQeUQzx)ZuISwS+peg(8JSwZqd{R%+{oU^(prc=X776&|uBo zQwt$9=#D^_Zk$e?ND_5N)a&jgY44zL6v?81qx2gB<-Jfbof^U5laz2oSf!sD#e)^K z$0UOlb-eW(@NlJC!y;jTA{sfV>iUiAh@{#oN{!@5#iX7DA)wG%F(=i%K9l-(O3yCI zL{b%S6bS=pN zh+U*kC8_$*9TspnNwRHzLqIXv#BdZ3Rn&$_62+rMA^bn)-aNjl>gwY@=iZx;aBmwrqFT5R6mZ|%MBUAgd7KJP#8yFb}?f6qGWtUd3u&ycfOM|0t^*9goA zzgR@EYMX{lBjOZB97X29Sfo5PoB_`oVaOwNL9;mJ^bxN_HYbyzSoDk(qcj}GbT~G? zU%+R<4~J(JjMyd})Q!M1R_C~%&6f5i!c&J0g&`Xk?J%VbS&h`c zz;0(Fq&=RuoO>0?40wDS-uM6ABMrZD^P1Z=O)Yiau*FSF>xR`9iIS!^3?}YgeGM9c*VU3~j@95ML;2X#pU+u|s65zIjBny0+HtYhKXK!=Y8*ti(&}mNwgiYb-R@ zwbfhIwwmTB(+3Sqhp`1nMq*aBnqx2y1XvHj9ljq7VP!i%xGFV(UoSNUzoFD*{QAO4 zskn&=rX-Mx3+~_=(G230><8U1kG)vr{vp5JM3Q7}GA>_^6;0d%v+?1+GR4Wk6xkcF z`m`L^Y)uWJRC$cgR0~OZtc==0N%0yvz6bM=+LLVwS!NRr;+`)u0!eVSCgxkc2=jcgSU1&X zDlEt%g)v*Ov1$m4c~hOHGJ+D7FZuy#9Hxo1h$JI5qOvHh>oG)Y>UxdM6jN#1k2y3& zo+noO($lUS1wV@Ik9)kkX~`88~GQfxBA*qbbEsXJ>T)(WHmKbNGLW^PK_6d-uR%kbDT%jG&MHX)wI>s^1#Nr6>S{2 zn2(xf3`x{r8e3q!t$ul(*IslAcDm%Y)GUuyH#SCF>K83;i`LaHs`HlA)xl_ETeP(f zF>p|f)~u{)sIM`0OrcC4J99#G`m|}~k_2ipc6TVo-L|@x2En>pPx1%py)s%|qoODm>FXUrTwbG(gz5elnu zQMUXXQbMh5)opcN3zHyY`JtI=jg9fqhU(Tf$*Cl-5yi=|Ji4%@4rSL^U9+UF)|)VS zs#Hd_$eTEIX7;#jIZ0&?UCQ`TXAQ03HdMvXR@4mI%Fu>-6i7AYi?WAKLx2;{m_?24 zqef*9UD(((w7#*SzOioT!uCedhr+_@2Gnz0GG+v1Zojijz1r%w>e#kdURqfdEgg53 z*Vfb)0QQTVQcY)go>JdbBVZ(RAb z%E?nFdMrVdlc}gFrE|R2;l*fjEp4cEsV>tJqs=u7TD{u#X6UwhI2|@gXK+m?-p)kq z)hw=V@tWIO*jQkVk;QuiTPkNC!)!BaEvP{ogK%km13IJE+E^RCprOcy#gYow>)2b+ zcB#^^V1e$`tqs+O^tP?F)T$DH`S;n=lUYD6g8b6ZFUKocynD#D+Yt; z0&F&+mFp43YaeO4sqLVRb#=99TrG7=o7(D3w|Cu>eSRiRL-r8 za#)%+v+B?e6&nv*+S=+`+v24vt;4n-F*CDFhF3e-VM>SY%i*MHIg9SXI?Suge9IeO zSyeg~qwu8hWu_ugV@s=7c&)8%i(Bei7mJV$QS4Tf&gQV~MHkn$pdUnAT9;#llyQ}2 z+g3K$IV+|jy9^t8Xg5O^iVT*#RvA9=DUP?6%JCDu%DGdcl{kf%QMMju8;?T`TUL~}%Ix`x zQ`2~Hqh-KsJt{!PK%O34labsnYp-js<1kUPcu8yfQaKQ1*;d^W(`!YGtXclw+f>=4 zansR=nuwz40`vT-r&MG)!d4ro{ zqp8ZE+~zg5w5{-#VwA;5!gj_&su(w`jCSWMfK!s{(J1T%JTHH!f`QW@4Nv9a}lAd}h^nOaiLLSCp1ljw$S3I(G7y zqV7h!O0r1r4#WCIY>9{gv9(%wuJ)_}qA5EBfbUKri zoEPy@=xBMgf_%+LK~| z+S8?9$9AX@+YWiLU0tTHF)0s7oR@alnQ(&bvhR>FvddmK3sLij0!|0L0y$w6EWp$D zf|k05>Hd4W!xa@OLgO-x~@hKBjOC-Sw(~Q3Tm2`F6AV(z}yWh zFwsg0p`y{^Z7kSmZfRaU43eGj|&C_yWQs(KB~3zu%s@W&Qnn z^+y=*nj_TPaD;k~9--c=N2vGJ_vo=~=?=n^aZ^!TVtqKh0Dwd4_vzu4#Y5`NoqidC zt6#o-;h6I67{jw6<_@vdHx}g@c!M7c>z4@n`@9okar$^4-wF&n2 zVB4MMwLQk8?PcM7&Qm(=9i{Bum0&M|^QAj|YkM6D_NK#_D?d)_T>73#u(ufY+-Y3f z`(uK=uVL?DC@_7;D0_Po?7ahf+1T%#%i~)K_U;)I&o9Rcm%adwhiYtmVS_Do#;hJU z`54^U=Jr0=Ye2~K9S861odA2f-Iu|hKF;y!N2tg3B96q~`8FR2#4+AN%M4t+d|kmY z_=Bydq8n*uvg21vd-D~VS>F4u*d&jr@cIQXKzD-z1OkhC!9}O z=S=@3!QKi~2LH#5_W0b+*}FTzUK8e&w?XEdv&ZkzI_ADqbe?}5M(+{GXglVnc=CVR zjCU}+i}$4jd;H+o{MbS9xV9zOdjf;Td(fl3li;1bw-fBmhrQ{CvG-I5~jaM_d$? zp0Bs{nVS0Sd2tt%l|uBku5Ie;mc?z|g1F6EiMt>l(JB{=pY=o+CRy9yA}j+1`HvpMmz)g3vk2-K`zUxcx(db=kM|`)=Xm^g@C+BhXP~{M zqY9``8yRSC1F+3L!|RF+%mhZOD&lby6Sn#CqI29|m$2QKu%@z?q2R;?p(wl zQc*wQs+^)jF2%dpjX&t9Yr}&Uq!fv%U5q5xG*!2>;^BbXUWlt$*{WZJ$6_LG#A8tG zw&NKamUX@zns~0lYk1-?B^PEdn_!vOjptf!MA&TkZiE+EUWf21CBMV+?gGaq5CWu|Sp(8kxEr$;h-Z)-qqp8gH5L zNP3tFI7vVBDI6Egvayi!aJEoQ2aHf;E!K}VAc*?5~PPcq4LQH#O@_v>lAj@sq zq)OWZGapi(ob17!0Z$#u$YCpI-Me^2-_{Gno*OHebpB5|9lI-;y0w;h&d9U87$NiM z%2WCU^eL16Zp#zXLa{@A8GoQdM$vn|O&iOCaZyHgX`W~0jF-;0X=aec2`!xD#m0py z5jkaKH-?CgJr?3verX~rgA$uBFm-XsAaahKI*(HC(4kD~-Nq|*0Xg+0E(+izkL=uV zjNWGfz_EUPRvcU&ygx=z+PTk4vn~_UN7_Ttcx1^p*nRJc?bFAYNk^M_`&x9_W*p~R z=CC%*GV7Vq(`E@mdS|nY%nZU!g6A6bjCYFSD$8uQ^T@C>A0fT7Q%lB}K(`p4Yu7Wq zOBJ_SW_hn7!_HcS^v=%ZWELdcRq$@D`)d{7WSMqux6H9*lVy%2cavfN9)$GH{{3V& z7PyDuGr`ERe8<)C7At3Vp0k{Wa3>iyUqMLkY`#uLAEes@p9!YTcNOom%&7O1Vdnrs zdS~ZrGAkeMAbcj6n|M7g#wnIrzdbFpe*2MOGaDhjvzbS>eJ7tfV5W`VZgtFihGgcK z^F!JxK}hfHl#$Wq=_XMJ%xdC)ygIJ3%%b31tCTZpT(*0@y-?#ZK06Z}_c>-B98=Zr zhab2cc%PLEmk;lB*tQ*WSaHm*<@hYc6^iF7p09Y3;%3FG6kR#yjk&Y6hE$* z?aHO|Pm2Gn_%p@-R?Ifwj?GleHD8>Z>%2JT{~$W%cf1`>ReZMMg^I6Ne7oXbD1J!s zONw7p{FP$7l^9C{*T8b=IZAO~#W{)xDdyT(?pUse<#?3hGZl|lEZ@|$?Qph|*C?)6 z+@yH9Vy;o;;(bu@9~5(KDW~(PVy*+_HpK@N^Tg%sq$%cFsZKsf@d(AGius?DPX8Rm@|{atU+qfH zbx@uD^@=wr{-xqa6hEzar{cF1f28|fMVV{a%sy{%(XO~yj1a2#S0W)sQ3!SH!A*_;ztxe zrI_nXx_JLeMqSdq4R&+6kCe^4Y;qtZVnm7?LlWVoosamkvTDg8>-}|l5IN2D4kNUn=8(u+@|v!rC+Dy z=aa4dixpq5^tnc&n?v3Pc5}$Pl+OKR8`l=a&nlgrO3pP8o&Mj*oS4CVsr0`k+d1cd zz;4co|8I%O)4-Gu!m(Uq-j&I5WSgE`B_FEf#Y#R#$)_l;P&(%-`BKF#WSh>56mtzj zCzo$q+WOi^IVYHKKL@+H?tM!BDB0>iO}6vf=csSzx4V@N*D7@R-K+HF`^eE*V@ zS-9`iv8ibL?s~Qd+3Ful=42j@{|D;iT$7OZN$9vHp_9*0e6Hda#j6$nP%&+}zKl~@ zjG+=^HW8=OTQRHI$@3KFD;}npNq71(C%0orsgh4pT(0;$#S0YIE9P~jv)`t8h2pCf z%Us>2;btY5dApT&DEVf^k0^dz@m9spDwbkrOOiQ&ejdWfH!0?4BAooUil0=xRWUy!;q?Ean4f!a)k zimz@I)p&U#bh48Mej-VXv z9McH7-{;DCH07ux%1hu~Udkv(*|KzHx4e6buHOF2*xj^*I`Z#LQXS(bz2e6nqCLlhU183`QA!SP74%@@nTaS7Sxi{;>0 z#tK_s=dga6Avk$Q#?}khO^&6L*OfM%)5tb$a_wo;Q;h<0@m@`~@pAmhKwMPgS5L^e zo#m~u%zH~ew44LJ#xmzN>n#rh|HN`J_zug=H^(B{91H%XW#;uamM4RMYk4a8_m-!F zw_2_MKWCZszr*q@@SiQu0dtIETxWydwmcvFzU4*We^_n+^UF)rZv-E-+y)M!Y$;y} z=Dip4YB2A;kS_=G-V6B(Fy9d)Uj^p4L|zBxJr?qh!DB4*TsqG3Pr#Ec-v*v$xdY7i z#CYu8;Duzg0k+u&#VwXuUmTaH!+FPQ%WTU(vdrnz4VJUPw^%L!^Ia|;%ew2ZTmpWG zjP}O<@t9@WdB$=cnD0+f=Oi%4C^FmrYnI1@|7!UMV7||kfxbqY2Q8ln4xrsqJ_?*- znSG^)W!lNId={ANqELSd_#`sgKeFKQy&y8Xz^Rtm^~PA{)N!0;&etYdW?p#zCj$r4 z&V0oSEhB4QgJt#?-Xo$uyAsz?A=Bn%mRT3PUqtx{V6Le`9th^WBXT~N>#LAi7rc)| zE(G6gndNz(WtPdqmf4SZuZjATz<;n@1>QwQBAL$DEOVOumSvVdzg$Nhrt?F~Y%`x( zW|{ocGW+|#Ee{3zA#?1>;E3f@!I_p>kH=U(1AKzz5->jz#CXSnPqNJV4VEVDoEvdnV+ zi{+7EIyYZse%v_%#dp~AS~lg(EL=XkJ4Z0S!=0x}C}+dA&c((2J7(S-=P4GO7`y1$ zUY*V)#cZQaK3{Qz;uVT7SA2uw4T|qp{IKFJino(lU~sR)JAO~`e#HkB%XI_?0k|xj zFWme=o*!BH5G5a}Se^%29ll%c&fW7A%Xyy#4A-XQYst3m)+v_xzm;#M9OD4p{fhP6 z{&^*TMe#d|KUVy;;ttQS+UHq zt^6v=ZJU&}xh(UX<>dD$ew54sACBiNcRyh#nS&wR9x^*DTy10QGwIoM-}kNb5vPnQ zIz=?U|6A#y>4*U1=Lm@@-z$+-wPmBrTb<_H*ZBPQf?hA&`QatsEK7ahyWoz%-W_=- zE}WCL;r-mSl;>_d=AD7P@Qv_E$K^hieq#T6e@xFUNnRu{IBl{2(pw+g@oMQuom=Mh zdU0mahn~$yl3L~v_Iq^ znBWd0O3>)KnXz@t3-1E+G{jPZx2MV|3r!xq9yXVSkf2-Mxcu$(0J0m%FMz@!Wb`H%R+Y#cik8^Ks zq@*~~bNk-0k#NqhJ4esVF6-EaZt2aqtF!d3&YWL#X7}&N51=gWr}mD(&@}%(($GlC z=g+_U`mTLjzkVQNYf0>D=eWfdbF7;(c=-lAK4dOs{zk9Vq7QwPc=qn>+(`F;q%bu<}yIKK-AuS>B+m_t20&`0+=%^Foo_ z-16>`KyGku+&`x#ejK#}?*B!h0Ufd9yP=W5ZbFcl#HS z%;NHJad`y0ljS^u8VUNZFjCou5#)21+s=<{U%;5Uqh!LlxeZ?LFaBdbcfZef-(g2K z#dUV#{fX0X!M`+OSz!kT9 zLqlWy$TJlkp8qb>J#bTC!Yy8IFE7%=w8veqbrz>}AJ{*z?OLz+xX_@?z!leEf50@v z?*h5Kg8r*Ka_}X&eqe2`|LUfkfhPo#f9U0=mFy`lP7CKe-#KZ$G>4IL_-b$Lj&!u( zHE4K4BV&3_eqiOD{x+JJ^uUTcZ+Y;zijFPQi_>TSIIykNE4g6HiB(YChN3abbGJhM z_eOorRvfVD*y50fDrC|Yd40<+tVLs@z$dwW&SUzGH`5Q!ffO%ZQvJyj%$i%FZ4!zwkisjEtcXe^@L%&Itu1YT?txNSHR_)<}1vwsEm54GuiTF^N-ZO}u3;-$#bS!4Vr(MX%MDG3$7aClYjl=X1xL ztwl3CPaH6){|F?&Ur5oUOXh41A2>UA|MUadg$L$dl7C6>OFv;29|~-HvNQRi&c2`S z-cdI2jKH>rPNd*$9uvsv^Hfgn-8o0?&B^*ACo^N~{IvbC!NBuapI_x3ReG@Vo!nk0 z=B*o!)hE!ix!A?1Ko`Bjww&)ezv`cqbC5%h?Be{-d5j?uER^B@n~_E`%;E@dClXJ&65A48~mm-;wz?S}(y|F9x^AER9E}c6gduQ9M zd-L}H`LbD4@^X86z4!JX+SA|1#C{SO^2G-a29mGwhV~p2@!z9tus`e4LCaq4 z^Aj#)F$^x+^=#+XZJm*%+#TQIa(&>S9(`v{pWcRQT6pq5CSV?fIMYUl=2pY5oGa#3 zuULk~N=8Q3eVIRc-HrJTvz|IQRMympWMt>wFtT*gj4e-fjEYR|S5cm_Z65x)?Khn{ z_jX2txL6t0>*B!JK=&PiCoW$&qUYE^kCI7SN=n)$J`|kOYfNZTuiU4~`aZK|OWO;* z7LI;(!a3fS0lm)7ZO-i|4s;)gF{&D;kGZ{yZtKhsZph6azV4~~npNM;3iOHO$_Y^7 zFD&lJ?=>nXcU(%*`c9lQ%e&_Wy-7K_)_S@8#Dr%2iKZ(c4>AOg1a?yl~J6C--@Z`XRO`UiOj)s9En&5kp{-gX) zf zeQ28d#t6Lm@SKwy-T5I-+1CY(K`iMZ*V7P*gIa8xmuS33wwFV4&Cbh!e(-dZ=fS%) zFiu`4x%|w*_8YNyOJog{bpfoHLL)Yn&K8elStZ)~2d)vg55N8ku;rhO2o|F-pBJI| z!8###BC%N5V@Wpzfuw?D2Hoz3FuqR6H&DhpAzU36>x3+VF{~3Zj+&uv?;?x97Cc~DIXU5Vq8F_d`S0#r6DhJ1@;1ZPa5l&{i+%;F)#APt$tL-J|StQf-kF(J2N z2rtmEVhF$Im-2Jb8U9aLN!^c>cN_625aH3VlXU9S!0w@>F-_PC&q7}CwlEG`6VAeM ztHYCE_Tup0Azu~d>n9h5d9ih2cogI-!#knABFuT}1>qD(mWQ`MvpxKGa9emVxHWtu z_O^tdgXXgE>-cR(bjg!$VRU?E<%PK@iy!9V9D#5aq7H^1h8Sy)3`A;^qf8i%sC$Y> z{0Muza5l93@D^q={C6CU|9^TC^5j)_LMP=pNYaz9E5Pnlp5>BnAbP34gFM+RGm^^n zRgyQ{3$a;dBzYsbd+I_)xoHzPlKKsG?joCIMw0KL4wo6>ed(moX|S5sV=p+Aa?07* z2yevEUid!R2=g1I1zxxANNUP~J&q!(N)&#(>A7+;dgi9d^hPlK*C|nAa zq%iMHCx_=kr(2k7E~JDnLp-VBPNb>3*JCAByDxc}=31oAZiERx{AZf;y7j|x;VJyj z)1=Tl`0d$=pY$bANf%;yr1M5&I&%aie(yVlHx=^3Gbm5Jh88NBDKGUeh`?|tbtVMi z%1!t+D;5|wD;5~;E@d8`&4^4HhUZd0J@p+Pdk$mFNG(P}4QHkD&8={haUGpnf?S5H zsoyX4T*iAo^O&9bBGc2r9ONOnyf2!}1G*JJ5?S~Rwv$3H;#9axk?Vk))$^Yr2fUQyk)4SDBJU#_r5#G?PogBt zx%e-$f0}g|{GF7ipzZjtJ%t0q#ZuX_)^_-xNJ1ct{b>Iwx1lu3{I@HSL}TS0>E)@_ zC=dT#mQ^TqFuToOv6$KuhWx)Vzui-h!(RVAa#$8~@!uy$QpZu}@8q=91E?7P19Fd4 zc`fTha?jLzP*(mw7;SoLE>h_4r@X}L#j≫*46rFfXM7sg3ww-2_qUFKF!R$B;Bn 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

2u zXh$tGc1Z$aQAw{b!*XL=T}xwiLsV`fL~9!Ap&#YCzgYObwr)k2hCFLT*UeMdBKa0% zto>GwpD2|p!=~r*=}y&BI5HT;2Zz$ivnEe92h}%X&0d@X+v+4Q3y=UYX8NvFO6gdf zb>auloQgAT84BK%l_`OxP0Q;

Z0CHQG=Ml-34+6KTyp`%mBS52OPGxp^1Q>&t7 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%0A31`q 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

    F)*snww`s8_mJ&n#VP3j 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

    nTYs?^Y8xi{&^f%e;>O)$PAHG( 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 OBfTKNR}qg2@c#qPSyj;h literal 0 HcmV?d00001 diff --git a/tools/sdk/lwip2/include/README.md b/tools/sdk/lwip2/include/README.md new file mode 100644 index 000000000..8cc8ecd2d --- /dev/null +++ b/tools/sdk/lwip2/include/README.md @@ -0,0 +1 @@ +warning: this directory is re/over/written from lwip2 builder upon lwip2 rebuild diff --git a/tools/sdk/lwip2/include/arch/cc.h b/tools/sdk/lwip2/include/arch/cc.h new file mode 100644 index 000000000..98046e42c --- /dev/null +++ b/tools/sdk/lwip2/include/arch/cc.h @@ -0,0 +1,145 @@ + +/* + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products +derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (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: d. gauchard + +*/ + +// version for esp8266 sdk-2.0.0(656edbf) + +#ifndef LWIP2_ARCH_CC_H +#define LWIP2_ARCH_CC_H + +#include "stdint.h" + +#include "lwip-err-t.h" + +#ifdef LWIP_BUILD + +// define LWIP_BUILD only when building LWIP +// otherwise include files below would conflict +// with standard headers like atoi() +#ifdef __cplusplus +extern "C" +{ +#endif +#include "ets_sys.h" +#include "osapi.h" +#include "esp-missing.h" +#ifdef __cplusplus +} +#endif + +void sntp_set_system_time (uint32_t t); + +#endif // defined(LWIP_BUILD) + +#include "mem.h" // useful for os_malloc used in esp-arduino's mDNS + +typedef uint32_t sys_prot_t; // not really used +#define SYS_ARCH_DECL_PROTECT(lev) +#define SYS_ARCH_PROTECT(lev) os_intr_lock() +#define SYS_ARCH_UNPROTECT(lev) os_intr_unlock() + +/////////////////////////////// +//// DEBUG +#include "gluedebug.h" + +#if ULWIPDEBUG // debug 1:on or 0 +#define LWIP_DEBUG 1 +#define LWIP_PLATFORM_DIAG(x) do { os_printf x; } while(0) +#define LWIP_PLATFORM_ASSERT(x) do { os_printf("Assertion \"%s\" failed at line %d in %s\n", x, __LINE__, __FILE__); *(int*)0=0; } while(0) +//#define LWIP_PLATFORM_ASSERT(x) do { os_printf("Assertion \"%s\" failed at line %d in %s\n", x, __LINE__, __FILE__); while(1); } while(0) +#endif // ULWIPDEBUG + +#if !ULWIPASSERT +#define LWIP_NOASSERT 1 +#endif + +/////////////////////////////// +//// MISSING + +#define sys_now millis // arduino wire millis() definition returns 32 bits like sys_now() does +#define LWIP_RAND r_rand // old lwip uses this useful undocumented function +#define IPSTR "%d.%d.%d.%d" +#define IP2STR(ipaddr) ip4_addr1_16(ipaddr), \ + ip4_addr2_16(ipaddr), \ + ip4_addr3_16(ipaddr), \ + ip4_addr4_16(ipaddr) + +// ip_addr / ip_info: do not exist in lwip2 (only in lwip1.4) +struct ip_addr { + uint32_t addr; +}; +struct ip_info { + struct ip_addr ip; + struct ip_addr netmask; + struct ip_addr gw; +}; + +/////////////////////////////// +//// PROVIDED TO USER + +typedef struct ip4_addr ip4_addr_t; +extern int ntp_servers_number; +extern ip4_addr_t* ntp_servers; + +/////////////////////////////// +//// STUBS + +// these symbols must be renamed in the new implementation +// because they are known/used in blobs + +#define dhcp_cleanup dhcp_cleanup_LWIP2 +#define dhcp_release dhcp_release_LWIP2 +#define dhcp_start dhcp_start_LWIP2 +#define dhcp_stop dhcp_stop_LWIP2 +#define dhcps_start dhcps_start_LWIP2 +//#define dhcps_stop dhcps_stop_LWIP2 // void(void) +#define espconn_init espconn_init_LWIP2 +#define etharp_output etharp_output_LWIP2 +#define ethbroadcast ethbroadcast_LWIP2 +#define ethernet_input ethernet_input_LWIP2 +#define lwip_init lwip_init_LWIP2 +#define netif_add netif_add_LWIP2 +#define netif_default netif_default_LWIP2 +#define netif_remove netif_remove_LWIP2 +#define netif_set_addr netif_set_addr_LWIP2 +#define netif_set_default netif_set_default_LWIP2 +#define netif_set_down netif_set_down_LWIP2 +#define netif_set_up netif_set_up_LWIP2 +#define pbuf_alloc pbuf_alloc_LWIP2 +#define pbuf_free pbuf_free_LWIP2 +#define pbuf_ref pbuf_ref_LWIP2 +//#define sys_check_timeouts sys_check_timeouts_LWIP2 // void(void) + +#if !defined(LWIP_DEBUG) || !SYS_DEBUG +#define sys_timeout sys_timeout_LWIP2 +#endif + +#define sys_untimeout sys_untimeout_LWIP2 + +/////////////////////////////// +#endif // LWIP2_ARCH_CC_H diff --git a/tools/sdk/lwip2/include/arch/sys_arch.h b/tools/sdk/lwip2/include/arch/sys_arch.h new file mode 100644 index 000000000..abcf8afd0 --- /dev/null +++ b/tools/sdk/lwip2/include/arch/sys_arch.h @@ -0,0 +1,5 @@ + +#ifndef MYSYSARCH_H +#define MYSYSARCH_H + +#endif // MYSYSARCH_H \ No newline at end of file diff --git a/tools/sdk/lwip2/include/espconn.h b/tools/sdk/lwip2/include/espconn.h new file mode 100644 index 000000000..e69de29bb diff --git a/tools/sdk/lwip2/include/gluedebug.h b/tools/sdk/lwip2/include/gluedebug.h new file mode 100644 index 000000000..8750d6132 --- /dev/null +++ b/tools/sdk/lwip2/include/gluedebug.h @@ -0,0 +1,89 @@ + +#ifndef __GLUE_DEBUG_H +#define __GLUE_DEBUG_H + +///////////////////////////////////////////////////////////////////////////// +// user-definable + +// this is needed separately from lwipopts.h +// because it is shared by both sides of glue + +#define UDEBUG 0 // 0 or 1 (glue debug) +#define UDUMP 0 // 0 or 1 (glue / dump packet) +#define UDEBUGINDEX 0 // 0 or 1 (show debug line number) +#define UDEBUGSTORE 0 // 0 or 1 (store debug into buffer until doprint_allow=1=serial-available) + +#define ULWIPDEBUG 0 // 0 or 1 (trigger lwip debug) +#define ULWIPASSERT 0 // 0 or 1 (trigger lwip self-check, 0 saves flash) + +#define STRING_IN_FLASH 0 // *print("fmt is stored in flash") + +#define ROTBUFLEN_BIT 11 // (UDEBUGSTORE=1) doprint()'s buffer: 11=2048B + +#if ULWIPDEBUG +//#define LWIP_DBG_TYPES_ON (LWIP_DBG_ON|LWIP_DBG_TRACE|LWIP_DBG_STATE|LWIP_DBG_FRESH|LWIP_DBG_HALT) +//#define LWIP_DBG_TYPES_ON (LWIP_DBG_ON|LWIP_DBG_TRACE|LWIP_DBG_STATE|LWIP_DBG_FRESH) +#define LWIP_DBG_TYPES_ON (LWIP_DBG_ON) +#endif + +///////////////////////////////////////////////////////////////////////////// + +#if UDEBUG && UDEBUGSTORE +#warning use 'doprint_allow=1' right after Serial is enabled +extern int doprint_allow; +#endif + +// print definitions: +// uprint(): always used by glue, defined as doprint() in debug mode or nothing() +// os_printf(): can be redefined as doprint() +// doprint(): always print, can be os_printf_plus() or defined in doprint.c (buffered) +// in buffered mode: doprint_allow=1 is needed after Serial.begin + +#if STRING_IN_FLASH && !defined(USE_OPTIMIZE_PRINTF) +#define USE_OPTIMIZE_PRINTF // at least used in arduino/esp8266 +#endif +// os_printf_plus() missing in osapi.h (fixed in arduino's sdk-2.1): +extern int os_printf_plus (const char * format, ...) __attribute__ ((format (printf, 1, 2))); + +#include // os_printf* definitions + ICACHE_RODATA_ATTR + +#if UDEBUG && (UDEBUGINDEX || UDEBUGSTORE) +// doprint() is used + +#undef os_printf +#define os_printf(x...) do { doprint(x); } while (0) + +#if STRING_IN_FLASH + +#define doprint(fmt, ...) \ + do { \ + static const char flash_str[] ICACHE_RODATA_ATTR STORE_ATTR = fmt; \ + doprint_minus(flash_str, ##__VA_ARGS__); \ + } while(0) + +#else // !STRING_IN_FLASH + +#define doprint(fmt, ...) doprint_minus(fmt, ##__VA_ARGS__) + +#endif // !STRING_IN_FLASH + +int doprint_minus (const char* format, ...) __attribute__ ((format (printf, 1, 2))); // format in flash + +#else // !( UDEBUG && (UDEBUGINDEX || UDEBUGSTORE) ) + +#define doprint(x...) do { os_printf(x); } while (0) + +#endif // !( UDEBUG && (UDEBUGINDEX || UDEBUGSTORE) ) + +#if UDEBUG +#define uprint(x...) do { doprint(x); } while (0) +#else +#define uprint(x...) do { (void)0; } while (0) +#endif + +#define uerror(x...) do { doprint(x); } while (0) +#define uassert(assertion...) do { if ((assertion) == 0) { os_printf_plus("assert fail: " #assertion " @%s:%d\n", __FILE__, __LINE__); uhalt(); } } while (0) +#define uhalt() do { *((int*)0) = 0; /* this triggers gdb */ } while (0) +#define nl() do { uprint("\n"); } while (0) + +#endif diff --git a/tools/sdk/lwip2/include/lwip-err-t.h b/tools/sdk/lwip2/include/lwip-err-t.h new file mode 100644 index 000000000..f9ba97f19 --- /dev/null +++ b/tools/sdk/lwip2/include/lwip-err-t.h @@ -0,0 +1,10 @@ +// script-generated, extracted from espressif SDK's lwIP arch/cc.h +#define LWIP_NO_STDINT_H 1 +typedef unsigned char u8_t; +typedef signed char s8_t; +typedef unsigned short u16_t; +typedef signed short s16_t; +typedef unsigned long u32_t; +typedef signed long s32_t; +typedef unsigned long mem_ptr_t; +#define LWIP_ERR_T s32_t diff --git a/tools/sdk/lwip2/include/lwip-git-hash.h b/tools/sdk/lwip2/include/lwip-git-hash.h new file mode 100644 index 000000000..587ff5854 --- /dev/null +++ b/tools/sdk/lwip2/include/lwip-git-hash.h @@ -0,0 +1,6 @@ +// generated by makefiles/make-lwip2-hash +#ifndef LWIP_HASH_H +#define LWIP_HASH_H +#define LWIP_HASH 0x92f23d6 +#define LWIP_HASH_STR "92f23d6(tag:STABLE-2_0_3_RELEASE)" +#endif // LWIP_HASH_H diff --git a/tools/sdk/lwip2/include/lwip/api.h b/tools/sdk/lwip2/include/lwip/api.h new file mode 100644 index 000000000..516bd163d --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/apps/FILES b/tools/sdk/lwip2/include/lwip/apps/FILES new file mode 100644 index 000000000..adfc0f334 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/apps/fs.h b/tools/sdk/lwip2/include/lwip/apps/fs.h new file mode 100644 index 000000000..bb176fa01 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/apps/httpd.h b/tools/sdk/lwip2/include/lwip/apps/httpd.h new file mode 100644 index 000000000..40f1811e5 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/apps/httpd_opts.h b/tools/sdk/lwip2/include/lwip/apps/httpd_opts.h new file mode 100644 index 000000000..340db15f6 --- /dev/null +++ b/tools/sdk/lwip2/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 0 +#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 0 +#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_OFF +#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/tools/sdk/lwip2/include/lwip/apps/lwiperf.h b/tools/sdk/lwip2/include/lwip/apps/lwiperf.h new file mode 100644 index 000000000..7dbebb082 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/apps/mdns.h b/tools/sdk/lwip2/include/lwip/apps/mdns.h new file mode 100644 index 000000000..d03681611 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/apps/mdns_opts.h b/tools/sdk/lwip2/include/lwip/apps/mdns_opts.h new file mode 100644 index 000000000..bf186bcce --- /dev/null +++ b/tools/sdk/lwip2/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 0 +#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/tools/sdk/lwip2/include/lwip/apps/mdns_priv.h b/tools/sdk/lwip2/include/lwip/apps/mdns_priv.h new file mode 100644 index 000000000..8ee6db86a --- /dev/null +++ b/tools/sdk/lwip2/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 256 +#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/tools/sdk/lwip2/include/lwip/apps/mqtt.h b/tools/sdk/lwip2/include/lwip/apps/mqtt.h new file mode 100644 index 000000000..34b230b88 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/apps/mqtt_opts.h b/tools/sdk/lwip2/include/lwip/apps/mqtt_opts.h new file mode 100644 index 000000000..ffefacd25 --- /dev/null +++ b/tools/sdk/lwip2/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 256 +#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 128 +#endif + +/** + * Maximum number of pending subscribe, unsubscribe and publish requests to server . + */ +#ifndef MQTT_REQ_MAX_IN_FLIGHT +#define MQTT_REQ_MAX_IN_FLIGHT 4 +#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/tools/sdk/lwip2/include/lwip/apps/netbiosns.h b/tools/sdk/lwip2/include/lwip/apps/netbiosns.h new file mode 100644 index 000000000..c9f68d8d1 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/apps/netbiosns_opts.h b/tools/sdk/lwip2/include/lwip/apps/netbiosns_opts.h new file mode 100644 index 000000000..0909ef7b9 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/apps/snmp.h b/tools/sdk/lwip2/include/lwip/apps/snmp.h new file mode 100644 index 000000000..10e8ff434 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/apps/snmp_core.h b/tools/sdk/lwip2/include/lwip/apps/snmp_core.h new file mode 100644 index 000000000..e781c532b --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/apps/snmp_mib2.h b/tools/sdk/lwip2/include/lwip/apps/snmp_mib2.h new file mode 100644 index 000000000..2f4a68935 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/apps/snmp_opts.h b/tools/sdk/lwip2/include/lwip/apps/snmp_opts.h new file mode 100644 index 000000000..6c9ba7beb --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/apps/snmp_scalar.h b/tools/sdk/lwip2/include/lwip/apps/snmp_scalar.h new file mode 100644 index 000000000..40a060c64 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/apps/snmp_table.h b/tools/sdk/lwip2/include/lwip/apps/snmp_table.h new file mode 100644 index 000000000..4988b51c2 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/apps/snmp_threadsync.h b/tools/sdk/lwip2/include/lwip/apps/snmp_threadsync.h new file mode 100644 index 000000000..a25dbf2d0 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/apps/snmpv3.h b/tools/sdk/lwip2/include/lwip/apps/snmpv3.h new file mode 100644 index 000000000..c99fed4e1 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/apps/sntp.h b/tools/sdk/lwip2/include/lwip/apps/sntp.h new file mode 100644 index 000000000..40df9cc59 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/apps/sntp_opts.h b/tools/sdk/lwip2/include/lwip/apps/sntp_opts.h new file mode 100644 index 000000000..f3651f90e --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/apps/tftp_opts.h b/tools/sdk/lwip2/include/lwip/apps/tftp_opts.h new file mode 100644 index 000000000..6968a803b --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/apps/tftp_server.h b/tools/sdk/lwip2/include/lwip/apps/tftp_server.h new file mode 100644 index 000000000..3fbe701e0 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/arch.h b/tools/sdk/lwip2/include/lwip/arch.h new file mode 100644 index 000000000..55714e113 --- /dev/null +++ b/tools/sdk/lwip2/include/lwip/arch.h @@ -0,0 +1,319 @@ +/** + * @file + * Support for different processor and compiler architectures + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE 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" + +/** + * @defgroup compiler_abstraction Compiler/platform abstraction + * @ingroup sys_layer + * 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. + * @{ + */ + +/** Define the byte order of the system. + * Needed for conversion of network data to host byte order. + * Allowed values: LITTLE_ENDIAN and BIG_ENDIAN + */ +#ifndef BYTE_ORDER +#define BYTE_ORDER LITTLE_ENDIAN +#endif + +/** Define random number generator function of your system */ +#ifdef __DOXYGEN__ +#define LWIP_RAND() ((u32_t)rand()) +#endif + +/** Platform specific diagnostic output.\n + * Note the default implementation pulls in printf, which may + * in turn pull in a lot of standard libary code. In resource-constrained + * systems, this should be defined to something less resource-consuming. + */ +#ifndef LWIP_PLATFORM_DIAG +#define LWIP_PLATFORM_DIAG(x) do {printf x;} while(0) +#include +#include +#endif + +/** Platform specific assertion handling.\n + * Note the default implementation pulls in printf, fflush and abort, which may + * in turn pull in a lot of standard libary code. In resource-constrained + * systems, this should be defined to something less resource-consuming. + */ +#ifndef LWIP_PLATFORM_ASSERT +#define LWIP_PLATFORM_ASSERT(x) do {printf("Assertion \"%s\" failed at line %d in %s\n", \ + x, __LINE__, __FILE__); fflush(NULL); abort();} while(0) +#include +#include +#endif + +/** Define this to 1 in arch/cc.h of your port if you do not want to + * include stddef.h header to get size_t. You need to typedef size_t + * by yourself in this case. + */ +#ifndef LWIP_NO_STDDEF_H +#define LWIP_NO_STDDEF_H 0 +#endif + +#if !LWIP_NO_STDDEF_H +#include /* for size_t */ +#endif + +/** Define this to 1 in arch/cc.h of your port if your compiler does not provide + * the stdint.h header. You need to typedef the generic types listed in + * lwip/arch.h yourself in this case (u8_t, u16_t...). + */ +#ifndef LWIP_NO_STDINT_H +#define LWIP_NO_STDINT_H 0 +#endif + +/* Define generic types used in lwIP */ +#if !LWIP_NO_STDINT_H +#include +typedef uint8_t u8_t; +typedef int8_t s8_t; +typedef uint16_t u16_t; +typedef int16_t s16_t; +typedef uint32_t u32_t; +typedef int32_t s32_t; +typedef uintptr_t mem_ptr_t; +#endif + +/** Define this to 1 in arch/cc.h of your port if your compiler does not provide + * the inttypes.h header. You need to define the format strings listed in + * lwip/arch.h yourself in this case (X8_F, U16_F...). + */ +#ifndef LWIP_NO_INTTYPES_H +#define LWIP_NO_INTTYPES_H 0 +#endif + +/* Define (sn)printf formatters for these lwIP types */ +#if !LWIP_NO_INTTYPES_H +#include +#ifndef X8_F +#define X8_F "02" PRIx8 +#endif +#ifndef U16_F +#define U16_F PRIu16 +#endif +#ifndef S16_F +#define S16_F PRId16 +#endif +#ifndef X16_F +#define X16_F PRIx16 +#endif +#ifndef U32_F +#define U32_F PRIu32 +#endif +#ifndef S32_F +#define S32_F PRId32 +#endif +#ifndef X32_F +#define X32_F PRIx32 +#endif +#ifndef SZT_F +#define SZT_F PRIuPTR +#endif +#endif + +/** 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)((ptrdiff_t)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 + +/** Packed structs support. + * Placed BEFORE declaration of a packed struct.\n + * For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n + * A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here. + */ +#ifndef PACK_STRUCT_BEGIN +#define PACK_STRUCT_BEGIN +#endif /* PACK_STRUCT_BEGIN */ + +/** Packed structs support. + * Placed AFTER declaration of a packed struct.\n + * For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n + * A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here. + */ +#ifndef PACK_STRUCT_END +#define PACK_STRUCT_END +#endif /* PACK_STRUCT_END */ + +/** Packed structs support. + * Placed between end of declaration of a packed struct and trailing semicolon.\n + * For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n + * A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here. + */ +#ifndef PACK_STRUCT_STRUCT +#if defined(__GNUC__) || defined(__clang__) +#define PACK_STRUCT_STRUCT __attribute__((packed)) +#else +#define PACK_STRUCT_STRUCT +#endif +#endif /* PACK_STRUCT_STRUCT */ + +/** Packed structs support. + * Wraps u32_t and u16_t members.\n + * For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n + * A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here. + */ +#ifndef PACK_STRUCT_FIELD +#define PACK_STRUCT_FIELD(x) x +#endif /* PACK_STRUCT_FIELD */ + +/** Packed structs support. + * Wraps u8_t members, where some compilers warn that packing is not necessary.\n + * For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n + * A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here. + */ +#ifndef PACK_STRUCT_FLD_8 +#define PACK_STRUCT_FLD_8(x) PACK_STRUCT_FIELD(x) +#endif /* PACK_STRUCT_FLD_8 */ + +/** Packed structs support. + * Wraps members that are packed structs themselves, where some compilers warn that packing is not necessary.\n + * For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n + * A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here. + */ +#ifndef PACK_STRUCT_FLD_S +#define PACK_STRUCT_FLD_S(x) PACK_STRUCT_FIELD(x) +#endif /* PACK_STRUCT_FLD_S */ + +/** Packed structs support using \#include files before and after struct to be packed.\n + * The file included BEFORE the struct is "arch/bpstruct.h".\n + * The file included AFTER the struct is "arch/epstruct.h".\n + * This can be used to implement struct packing on MS Visual C compilers, see + * the Win32 port in the lwIP contrib repository for reference. + * For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n + * A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here. + */ +#ifdef __DOXYGEN__ +#define PACK_STRUCT_USE_INCLUDES +#endif + +/** Eliminates compiler warning about unused arguments (GCC -Wextra -Wunused). */ +#ifndef LWIP_UNUSED_ARG +#define LWIP_UNUSED_ARG(x) (void)x +#endif /* LWIP_UNUSED_ARG */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_ARCH_H */ diff --git a/tools/sdk/lwip2/include/lwip/autoip.h b/tools/sdk/lwip2/include/lwip/autoip.h new file mode 100644 index 000000000..1d85bccff --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/debug.h b/tools/sdk/lwip2/include/lwip/debug.h new file mode 100644 index 000000000..a142f1cff --- /dev/null +++ b/tools/sdk/lwip2/include/lwip/debug.h @@ -0,0 +1,167 @@ +/** + * @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" + +/** + * @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/tools/sdk/lwip2/include/lwip/def.h b/tools/sdk/lwip2/include/lwip/def.h new file mode 100644 index 000000000..82a9d896f --- /dev/null +++ b/tools/sdk/lwip2/include/lwip/def.h @@ -0,0 +1,141 @@ +/** + * @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 +#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/tools/sdk/lwip2/include/lwip/dhcp.h b/tools/sdk/lwip2/include/lwip/dhcp.h new file mode 100644 index 000000000..df932afb5 --- /dev/null +++ b/tools/sdk/lwip2/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 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/tools/sdk/lwip2/include/lwip/dhcp6.h b/tools/sdk/lwip2/include/lwip/dhcp6.h new file mode 100644 index 000000000..455336d37 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/dns.h b/tools/sdk/lwip2/include/lwip/dns.h new file mode 100644 index 000000000..1453d7234 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/err.h b/tools/sdk/lwip2/include/lwip/err.h new file mode 100644 index 000000000..84e528d1e --- /dev/null +++ b/tools/sdk/lwip2/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*/ + +/** 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; + +#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/tools/sdk/lwip2/include/lwip/errno.h b/tools/sdk/lwip2/include/lwip/errno.h new file mode 100644 index 000000000..641cffb09 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/etharp.h b/tools/sdk/lwip2/include/lwip/etharp.h new file mode 100644 index 000000000..7080a19d0 --- /dev/null +++ b/tools/sdk/lwip2/include/lwip/etharp.h @@ -0,0 +1,106 @@ +/** + * @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); + +#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/tools/sdk/lwip2/include/lwip/ethip6.h b/tools/sdk/lwip2/include/lwip/ethip6.h new file mode 100644 index 000000000..5e88dffd0 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/icmp.h b/tools/sdk/lwip2/include/lwip/icmp.h new file mode 100644 index 000000000..f5a31fd4c --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/icmp6.h b/tools/sdk/lwip2/include/lwip/icmp6.h new file mode 100644 index 000000000..a29dc8c1c --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/igmp.h b/tools/sdk/lwip2/include/lwip/igmp.h new file mode 100644 index 000000000..ffd80e680 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/inet.h b/tools/sdk/lwip2/include/lwip/inet.h new file mode 100644 index 000000000..4a34f0265 --- /dev/null +++ b/tools/sdk/lwip2/include/lwip/inet.h @@ -0,0 +1,172 @@ +/** + * @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" + +#ifdef __cplusplus +extern "C" { +#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 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; + +/* 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 + + +#ifndef INET_ADDRSTRLEN +#define INET_ADDRSTRLEN IP4ADDR_STRLEN_MAX +#endif +#if LWIP_IPV6 +#ifndef INET6_ADDRSTRLEN +#define INET6_ADDRSTRLEN IP6ADDR_STRLEN_MAX +#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)) + +/* 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)) +#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/tools/sdk/lwip2/include/lwip/inet_chksum.h b/tools/sdk/lwip2/include/lwip/inet_chksum.h new file mode 100644 index 000000000..4e23d7f19 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/init.h b/tools/sdk/lwip2/include/lwip/init.h new file mode 100644 index 000000000..3c234cb58 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/ip.h b/tools/sdk/lwip2/include/lwip/ip.h new file mode 100644 index 000000000..0673be9b4 --- /dev/null +++ b/tools/sdk/lwip2/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 "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/tools/sdk/lwip2/include/lwip/ip4.h b/tools/sdk/lwip2/include/lwip/ip4.h new file mode 100644 index 000000000..48246ecc2 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/ip4_addr.h b/tools/sdk/lwip2/include/lwip/ip4_addr.h new file mode 100644 index 000000000..51b46b8d4 --- /dev/null +++ b/tools/sdk/lwip2/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 + +/** 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; + +/** + * 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; + +/** 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) + +/* 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! */ + +/** 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))) + +#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); + +#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); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV4 */ + +#endif /* LWIP_HDR_IP_ADDR_H */ diff --git a/tools/sdk/lwip2/include/lwip/ip4_frag.h b/tools/sdk/lwip2/include/lwip/ip4_frag.h new file mode 100644 index 000000000..ed5bf14a3 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/ip6.h b/tools/sdk/lwip2/include/lwip/ip6.h new file mode 100644 index 000000000..099b94fb7 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/ip6_addr.h b/tools/sdk/lwip2/include/lwip/ip6_addr.h new file mode 100644 index 000000000..ee381aeb2 --- /dev/null +++ b/tools/sdk/lwip2/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 + + +/** 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); + + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV6 */ + +#endif /* LWIP_HDR_IP6_ADDR_H */ diff --git a/tools/sdk/lwip2/include/lwip/ip6_frag.h b/tools/sdk/lwip2/include/lwip/ip6_frag.h new file mode 100644 index 000000000..6be274734 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/ip_addr.h b/tools/sdk/lwip2/include/lwip/ip_addr.h new file mode 100644 index 000000000..11f65d25b --- /dev/null +++ b/tools/sdk/lwip2/include/lwip/ip_addr.h @@ -0,0 +1,407 @@ +/** + * @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" + +#ifdef __cplusplus +extern "C" { +#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 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 */ + +#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/tools/sdk/lwip2/include/lwip/mem.h b/tools/sdk/lwip2/include/lwip/mem.h new file mode 100644 index 000000000..ff208d25c --- /dev/null +++ b/tools/sdk/lwip2/include/lwip/mem.h @@ -0,0 +1,82 @@ +/** + * @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" + +#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/tools/sdk/lwip2/include/lwip/memp.h b/tools/sdk/lwip2/include/lwip/memp.h new file mode 100644 index 000000000..562cd05bf --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/mld6.h b/tools/sdk/lwip2/include/lwip/mld6.h new file mode 100644 index 000000000..7fa0797f2 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/nd6.h b/tools/sdk/lwip2/include/lwip/nd6.h new file mode 100644 index 000000000..8204fa4cc --- /dev/null +++ b/tools/sdk/lwip2/include/lwip/nd6.h @@ -0,0 +1,84 @@ +/** + * @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" + +#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/tools/sdk/lwip2/include/lwip/netbuf.h b/tools/sdk/lwip2/include/lwip/netbuf.h new file mode 100644 index 000000000..e6865f80f --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/netdb.h b/tools/sdk/lwip2/include/lwip/netdb.h new file mode 100644 index 000000000..d3d15dfac --- /dev/null +++ b/tools/sdk/lwip2/include/lwip/netdb.h @@ -0,0 +1,150 @@ +/** + * @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" + +#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 +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 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/tools/sdk/lwip2/include/lwip/netif.h b/tools/sdk/lwip2/include/lwip/netif.h new file mode 100644 index 000000000..67a2d24de --- /dev/null +++ b/tools/sdk/lwip2/include/lwip/netif.h @@ -0,0 +1,474 @@ +/** + * @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 + +/* 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 + +/** + * @} + */ + +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); +#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 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 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/tools/sdk/lwip2/include/lwip/netifapi.h b/tools/sdk/lwip2/include/lwip/netifapi.h new file mode 100644 index 000000000..8bd2b4f76 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/opt.h b/tools/sdk/lwip2/include/lwip/opt.h new file mode 100644 index 000000000..fd459af14 --- /dev/null +++ b/tools/sdk/lwip2/include/lwip/opt.h @@ -0,0 +1,2876 @@ +/** + * @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 0 +#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 0 +#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 0 +#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 0 +#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 0 +#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 0 +#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 20000 +#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_OFF +#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_OFF +#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/tools/sdk/lwip2/include/lwip/pbuf.h b/tools/sdk/lwip2/include/lwip/pbuf.h new file mode 100644 index 000000000..90610461e --- /dev/null +++ b/tools/sdk/lwip2/include/lwip/pbuf.h @@ -0,0 +1,263 @@ +/** + * @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" + +#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 + +/** + * @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; + + +/** 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 + +/** 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; +}; + + +/** 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/tools/sdk/lwip2/include/lwip/priv/api_msg.h b/tools/sdk/lwip2/include/lwip/priv/api_msg.h new file mode 100644 index 000000000..f12b8b7d4 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/priv/memp_priv.h b/tools/sdk/lwip2/include/lwip/priv/memp_priv.h new file mode 100644 index 000000000..f246061da --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/priv/memp_std.h b/tools/sdk/lwip2/include/lwip/priv/memp_std.h new file mode 100644 index 000000000..ce9fd5003 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/priv/nd6_priv.h b/tools/sdk/lwip2/include/lwip/priv/nd6_priv.h new file mode 100644 index 000000000..4bda0b793 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/priv/tcp_priv.h b/tools/sdk/lwip2/include/lwip/priv/tcp_priv.h new file mode 100644 index 000000000..73e8967e4 --- /dev/null +++ b/tools/sdk/lwip2/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 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 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/tools/sdk/lwip2/include/lwip/priv/tcpip_priv.h b/tools/sdk/lwip2/include/lwip/priv/tcpip_priv.h new file mode 100644 index 000000000..630efb140 --- /dev/null +++ b/tools/sdk/lwip2/include/lwip/priv/tcpip_priv.h @@ -0,0 +1,160 @@ +/** + * @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 +}; + +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 */ + } msg; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* !NO_SYS */ + +#endif /* LWIP_HDR_TCPIP_PRIV_H */ diff --git a/tools/sdk/lwip2/include/lwip/prot/autoip.h b/tools/sdk/lwip2/include/lwip/prot/autoip.h new file mode 100644 index 000000000..fd3af8a9f --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/prot/dhcp.h b/tools/sdk/lwip2/include/lwip/prot/dhcp.h new file mode 100644 index 000000000..112953cb8 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/prot/dns.h b/tools/sdk/lwip2/include/lwip/prot/dns.h new file mode 100644 index 000000000..94782d6e9 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/prot/etharp.h b/tools/sdk/lwip2/include/lwip/prot/etharp.h new file mode 100644 index 000000000..ec78305b8 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/prot/ethernet.h b/tools/sdk/lwip2/include/lwip/prot/ethernet.h new file mode 100644 index 000000000..e4baa29dc --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/prot/icmp.h b/tools/sdk/lwip2/include/lwip/prot/icmp.h new file mode 100644 index 000000000..7d19385c7 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/prot/icmp6.h b/tools/sdk/lwip2/include/lwip/prot/icmp6.h new file mode 100644 index 000000000..346112042 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/prot/igmp.h b/tools/sdk/lwip2/include/lwip/prot/igmp.h new file mode 100644 index 000000000..d60cb31ee --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/prot/ip.h b/tools/sdk/lwip2/include/lwip/prot/ip.h new file mode 100644 index 000000000..bbfae3675 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/prot/ip4.h b/tools/sdk/lwip2/include/lwip/prot/ip4.h new file mode 100644 index 000000000..bd442c689 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/prot/ip6.h b/tools/sdk/lwip2/include/lwip/prot/ip6.h new file mode 100644 index 000000000..6e1e2632b --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/prot/mld6.h b/tools/sdk/lwip2/include/lwip/prot/mld6.h new file mode 100644 index 000000000..be3a006af --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/prot/nd6.h b/tools/sdk/lwip2/include/lwip/prot/nd6.h new file mode 100644 index 000000000..2d4903d15 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/prot/tcp.h b/tools/sdk/lwip2/include/lwip/prot/tcp.h new file mode 100644 index 000000000..67fe7b9e5 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/prot/udp.h b/tools/sdk/lwip2/include/lwip/prot/udp.h new file mode 100644 index 000000000..664f19a3e --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/raw.h b/tools/sdk/lwip2/include/lwip/raw.h new file mode 100644 index 000000000..30aa14710 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/sio.h b/tools/sdk/lwip2/include/lwip/sio.h new file mode 100644 index 000000000..7643e1956 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/snmp.h b/tools/sdk/lwip2/include/lwip/snmp.h new file mode 100644 index 000000000..8704d0b4d --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/sockets.h b/tools/sdk/lwip2/include/lwip/sockets.h new file mode 100644 index 000000000..2522056db --- /dev/null +++ b/tools/sdk/lwip2/include/lwip/sockets.h @@ -0,0 +1,593 @@ +/** + * @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" + +#ifdef __cplusplus +extern "C" { +#endif + +/* 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; + +#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; +}; + +/* 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 */ + +#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 +/** @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) + +#if LWIP_POSIX_SOCKETS_IO_NAMES +/** @ingroup socket */ +#define read(s,mem,len) lwip_read(s,mem,len) +/** @ingroup socket */ +#define write(s,dataptr,len) lwip_write(s,dataptr,len) +/** @ingroup socket */ +#define writev(s,iov,iovcnt) lwip_writev(s,iov,iovcnt) +/** @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 /* LWIP_POSIX_SOCKETS_IO_NAMES */ +#endif /* LWIP_COMPAT_SOCKETS != 2 */ + +#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 /* LWIP_COMPAT_SOCKETS */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_SOCKET */ + +#endif /* LWIP_HDR_SOCKETS_H */ diff --git a/tools/sdk/lwip2/include/lwip/stats.h b/tools/sdk/lwip2/include/lwip/stats.h new file mode 100644 index 000000000..5cde4a094 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/sys.h b/tools/sdk/lwip2/include/lwip/sys.h new file mode 100644 index 000000000..d12bae0f9 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/lwip/tcp.h b/tools/sdk/lwip2/include/lwip/tcp.h new file mode 100644 index 000000000..34d1c1015 --- /dev/null +++ b/tools/sdk/lwip2/include/lwip/tcp.h @@ -0,0 +1,433 @@ +/** + * @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); + +#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 */ +#define tcp_sndbuf(pcb) (TCPWND16((pcb)->snd_buf)) +#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/tools/sdk/lwip2/include/lwip/tcpip.h b/tools/sdk/lwip2/include/lwip/tcpip.h new file mode 100644 index 000000000..f2f6b469f --- /dev/null +++ b/tools/sdk/lwip2/include/lwip/tcpip.h @@ -0,0 +1,106 @@ +/** + * @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); + +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/tools/sdk/lwip2/include/lwip/timeouts.h b/tools/sdk/lwip2/include/lwip/timeouts.h new file mode 100644 index 000000000..c9b93aa02 --- /dev/null +++ b/tools/sdk/lwip2/include/lwip/timeouts.h @@ -0,0 +1,121 @@ +/** + * @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(u32_t msecs, sys_timeout_handler handler, void *arg, const char* handler_name); +#define sys_timeout(msecs, handler, arg) sys_timeout_debug(msecs, handler, arg, #handler) +#else /* LWIP_DEBUG_TIMERNAMES */ +void sys_timeout(u32_t msecs, sys_timeout_handler handler, void *arg); +#endif /* LWIP_DEBUG_TIMERNAMES */ + +void sys_untimeout(sys_timeout_handler handler, void *arg); +void sys_restart_timeouts(void); +#if NO_SYS +void sys_check_timeouts(void); +u32_t sys_timeouts_sleeptime(void); +#else /* NO_SYS */ +void sys_timeouts_mbox_fetch(sys_mbox_t *mbox, void **msg); +#endif /* NO_SYS */ + + +#endif /* LWIP_TIMERS */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_TIMEOUTS_H */ diff --git a/tools/sdk/lwip2/include/lwip/udp.h b/tools/sdk/lwip2/include/lwip/udp.h new file mode 100644 index 000000000..b92990739 --- /dev/null +++ b/tools/sdk/lwip2/include/lwip/udp.h @@ -0,0 +1,182 @@ +/** + * @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); + +#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/tools/sdk/lwip2/include/lwipopts.h b/tools/sdk/lwip2/include/lwipopts.h new file mode 100644 index 000000000..a9c1c2a5d --- /dev/null +++ b/tools/sdk/lwip2/include/lwipopts.h @@ -0,0 +1,3002 @@ +// this file will be overwritten upon lwip2 rebuild +#ifndef __CUSTOM_EXTRA_DEFINES__ +#define __CUSTOM_EXTRA_DEFINES__ + +#endif + +#ifndef MYLWIPOPTS_H +#define MYLWIPOPTS_H + +// opt.h version lwip-2.0.3 for esp8266 + +/** + * @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 + */ + +/* + * Include user defined options first. Anything not defined in these files + * will be set to standard values. Override anything you don't like! + */ +//#include "lwip/debug.h" // done at end of this file +#include "gluedebug.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 1 +#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) os_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) os_memcpy(dst,src,len) +#endif + +/** + * MEMMOVE: override this if you have a faster implementation at hand than the + * one included in your C library. lwIP currently uses MEMMOVE only when IPv6 + * fragmentation support is enabled. + */ +#if !defined MEMMOVE || defined __DOXYGEN__ +#define MEMMOVE(dst,src,len) os_memmove(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 0 +#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 1 +#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 1 +#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 4 +#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 16000 +#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 0 +#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 0 +#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 10 +#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 (*(volatile uint32*)0x600011FC) // 5 +#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 2 +#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 10 // 5 +#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 0 // 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 0 // 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 10 // 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 0 // 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 0 // 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 4 // 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 4 // 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 0 // 1 +#endif + +/** + * PBUF_POOL_SIZE: the number of buffers in the pbuf pool. + */ +#if !defined PBUF_POOL_SIZE || defined __DOXYGEN__ +#define PBUF_POOL_SIZE 10 // 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 1 // 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 // 0 // 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 !LWIP_SINGLE_NETIF +#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 0 // 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 0 // 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 // 0 +#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 1 // 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 0 // ((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 1 +#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 options ------- + ---------------------------------- +*/ +/** + * @defgroup lwip_opts_multicast Multicast + * @ingroup lwip_opts_infrastructure + * @{ + */ +/** + * LWIP_MULTICAST_TX_OPTIONS==1: Enable multicast TX support like the socket options + * IP_MULTICAST_TTL/IP_MULTICAST_IF/IP_MULTICAST_LOOP, as well as (currently only) + * core support for the corresponding IPv6 options. + */ +#if !defined LWIP_MULTICAST_TX_OPTIONS || defined __DOXYGEN__ +#define LWIP_MULTICAST_TX_OPTIONS ((LWIP_IGMP || LWIP_IPV6_MLD) && (LWIP_UDP || LWIP_RAW)) +#endif +/** + * @} + */ + +/* + ---------------------------------- + ---------- 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 1 +#endif +#if !LWIP_IPV4 +#undef LWIP_IGMP +#define LWIP_IGMP 0 +#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 1 // 0 +#endif + +/** DNS maximum number of entries to maintain locally. */ +#if !defined DNS_TABLE_SIZE || defined __DOXYGEN__ +#define DNS_TABLE_SIZE 3 // 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 48 // 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 1 +#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 (*(volatile uint32*)0x600011F0) // (4 * TCP_MSS) +#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 (*(volatile uint32*)0x600011E8) // 12 +#define TCP_MAXRTX 12 +#endif + +/** + * TCP_SYNMAXRTX: Maximum number of retransmissions of SYN segments. + */ +#if !defined TCP_SYNMAXRTX || defined __DOXYGEN__ +//#define TCP_SYNMAXRTX (*(volatile uint32*)0x600011E4) // 6 +#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 0 // (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 36 // 0u # 36 is EP_OFFSET from original esp implementation +#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 + +/** + * LWIP_PBUF_REF_T: Refcount type in pbuf. + * Default width of u8_t can be increased if 255 refs are not enough for you. + */ +#ifndef LWIP_PBUF_REF_T +#define LWIP_PBUF_REF_T u8_t +#endif +/** + * @} + */ + +/* + ------------------------------------------------ + ---------- Network Interfaces options ---------- + ------------------------------------------------ +*/ +/** + * @defgroup lwip_opts_netif NETIF + * @ingroup lwip_opts + * @{ + */ +/** + * LWIP_SINGLE_NETIF==1: use a single netif only. This is the common case for + * small real-life targets. Some code like routing etc. can be left out. + */ +#if !defined LWIP_SINGLE_NETIF || defined __DOXYGEN__ +#define LWIP_SINGLE_NETIF 0 // AP+STA = 2 different netif +#endif + +/** + * LWIP_NETIF_HOSTNAME==1: use DHCP_OPTION_HOSTNAME with netif's hostname + * field. + */ +#if !defined LWIP_NETIF_HOSTNAME || defined __DOXYGEN__ +#define LWIP_NETIF_HOSTNAME 1 +#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 1 +#endif + +/** + * LWIP_NETIF_EXT_STATUS_CALLBACK==1: Support an extended callback function + * for several netif related event that supports multiple subscribers. + * @see netif_ext_status_callback + */ +#if !defined LWIP_NETIF_EXT_STATUS_CALLBACK || defined __DOXYGEN__ +#define LWIP_NETIF_EXT_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 1 // MANDATORY FOR ESP8266 BLOBS !! +#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 0 +#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 && !LWIP_SINGLE_NETIF) +#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 0 // 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 0 // 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 0 // 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 1 // 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 0 +#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 0 +#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 20000 +#endif + +/** + * SO_REUSE==1: Enable SO_REUSEADDR option. + */ +#if !defined SO_REUSE || defined __DOXYGEN__ +#define SO_REUSE 1 // 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 + +/** + * LWIP_SOCKET_SELECT==1 (default): enable select() for sockets (uses a netconn + * callback to keep track of events). + * This saves RAM (counters per socket) and code (netconn event callback), which + * should improve performance a bit). + */ +#if !defined LWIP_SOCKET_SELECT || defined __DOXYGEN__ +#define LWIP_SOCKET_SELECT 1 +#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 0 // 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 1 // 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_SCOPES==1: Enable support for IPv6 address scopes, ensuring that + * e.g. link-local addresses are really treated as link-local. Disable this + * setting only for single-interface configurations. + */ +#if !defined LWIP_IPV6_SCOPES || defined __DOXYGEN__ +#define LWIP_IPV6_SCOPES (LWIP_IPV6 && !LWIP_SINGLE_NETIF) +#endif + +/** + * LWIP_IPV6_SCOPES_DEBUG==1: Perform run-time checks to verify that addresses + * are properly zoned (see ip6_zone.h on what that means) where it matters. + * Enabling this setting is highly recommended when upgrading from an existing + * installation that is not yet scope-aware; otherwise it may be too expensive. + */ +#if !defined LWIP_IPV6_SCOPES_DEBUG || defined __DOXYGEN__ +#define LWIP_IPV6_SCOPES_DEBUG 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 (LWIP_IPV6) // 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_ADDRESS_LIFETIMES==1: Keep valid and preferred lifetimes for each + * IPv6 address. Required for LWIP_IPV6_AUTOCONFIG. May still be enabled + * otherwise, in which case the application may assign address lifetimes with + * the appropriate macros. Addresses with no lifetime are assumed to be static. + * If this option is disabled, all addresses are assumed to be static. + */ +#if !defined LWIP_IPV6_ADDRESS_LIFETIMES || defined __DOXYGEN__ +#define LWIP_IPV6_ADDRESS_LIFETIMES (LWIP_IPV6_AUTOCONFIG) +#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|LWIP_DBG_TRACE|LWIP_DBG_STATE|LWIP_DBG_FRESH) +#endif + +/** + * ETHARP_DEBUG: Enable debugging in etharp.c. + */ +#if !defined ETHARP_DEBUG || defined __DOXYGEN__ +#define ETHARP_DEBUG LWIP_DBG_OFF//LWIP_DBG_OFF +#endif + +/** + * NETIF_DEBUG: Enable debugging in netif.c. + */ +#if !defined NETIF_DEBUG || defined __DOXYGEN__ +#define NETIF_DEBUG LWIP_DBG_OFF//LWIP_DBG_OFF +#endif + +/** + * PBUF_DEBUG: Enable debugging in pbuf.c. + */ +#if !defined PBUF_DEBUG || defined __DOXYGEN__ +#define PBUF_DEBUG LWIP_DBG_OFF//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//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//LWIP_DBG_OFF +#endif + +/** + * SOCKETS_DEBUG: Enable debugging in sockets.c. + */ +#if !defined SOCKETS_DEBUG || defined __DOXYGEN__ +#define SOCKETS_DEBUG LWIP_DBG_OFF +#endif + +/** + * ICMP_DEBUG: Enable debugging in icmp.c. + */ +#if !defined ICMP_DEBUG || defined __DOXYGEN__ +#define ICMP_DEBUG LWIP_DBG_OFF//LWIP_DBG_OFF +#endif + +/** + * IGMP_DEBUG: Enable debugging in igmp.c. + */ +#if !defined IGMP_DEBUG || defined __DOXYGEN__ +#define IGMP_DEBUG LWIP_DBG_OFF//LWIP_DBG_OFF +#endif + +/** + * INET_DEBUG: Enable debugging in inet.c. + */ +#if !defined INET_DEBUG || defined __DOXYGEN__ +//#define INET_DEBUG LWIP_DBG_OFF +#define INET_DEBUG LWIP_DBG_TYPES_ON +#endif + +/** + * IP_DEBUG: Enable debugging for IP. + */ +#if !defined IP_DEBUG || defined __DOXYGEN__ +//#define IP_DEBUG LWIP_DBG_OFF +#define IP_DEBUG LWIP_DBG_TYPES_ON +#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//LWIP_DBG_OFF +#endif + +/** + * RAW_DEBUG: Enable debugging in raw.c. + */ +#if !defined RAW_DEBUG || defined __DOXYGEN__ +#define RAW_DEBUG LWIP_DBG_OFF//LWIP_DBG_OFF +#endif + +/** + * MEM_DEBUG: Enable debugging in mem.c. + */ +#if !defined MEM_DEBUG || defined __DOXYGEN__ +#define MEM_DEBUG LWIP_DBG_OFF//LWIP_DBG_OFF +#endif + +/** + * MEMP_DEBUG: Enable debugging in memp.c. + */ +#if !defined MEMP_DEBUG || defined __DOXYGEN__ +#define MEMP_DEBUG LWIP_DBG_OFF//LWIP_DBG_OFF +#endif + +/** + * SYS_DEBUG: Enable debugging in sys.c. + */ +#if !defined SYS_DEBUG || defined __DOXYGEN__ +#define SYS_DEBUG LWIP_DBG_OFF//LWIP_DBG_OFF +#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//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//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//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//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//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//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//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//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//LWIP_DBG_OFF +#endif + +/** + * UDP_DEBUG: Enable debugging in UDP. + */ +#if !defined UDP_DEBUG || defined __DOXYGEN__ +//#define UDP_DEBUG LWIP_DBG_OFF +#define UDP_DEBUG LWIP_DBG_TYPES_ON +#endif + +/** + * TCPIP_DEBUG: Enable debugging in tcpip.c. + */ +#if !defined TCPIP_DEBUG || defined __DOXYGEN__ +#define TCPIP_DEBUG LWIP_DBG_OFF +//#define TCPIP_DEBUG LWIP_DBG_TYPES_ON +#endif + +/** + * SLIP_DEBUG: Enable debugging in slipif.c. + */ +#if !defined SLIP_DEBUG || defined __DOXYGEN__ +#define SLIP_DEBUG LWIP_DBG_OFF//LWIP_DBG_OFF +#endif + +/** + * DHCP_DEBUG: Enable debugging in dhcp.c. + */ +#if !defined DHCP_DEBUG || defined __DOXYGEN__ +//#define DHCP_DEBUG LWIP_DBG_OFF +#define DHCP_DEBUG LWIP_DBG_TYPES_ON +#endif + +/** + * AUTOIP_DEBUG: Enable debugging in autoip.c. + */ +#if !defined AUTOIP_DEBUG || defined __DOXYGEN__ +#define AUTOIP_DEBUG LWIP_DBG_OFF//LWIP_DBG_OFF +#endif + +/** + * DNS_DEBUG: Enable debugging for DNS. + */ +#if !defined DNS_DEBUG || defined __DOXYGEN__ +#define DNS_DEBUG LWIP_DBG_OFF//LWIP_DBG_OFF +#endif + +/** + * IP6_DEBUG: Enable debugging for IPv6. + */ +#if !defined IP6_DEBUG || defined __DOXYGEN__ +#define IP6_DEBUG LWIP_DBG_OFF//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 +/** + * @} + */ + + +/* + -------------------------------------------------- + ------------------ SNTP options ------------------ + -------------------------------------------------- +*/ +#define SNTP_SERVER_DNS 1 // SNTP support DNS names through sntp_setservername / sntp_getservername +#define SNTP_SERVER_ADDRESS "pool.ntp.org" // default +#define SNTP_GET_SERVERS_FROM_DHCP 1 +#define SNTP_SET_SYSTEM_TIME(t) (sntp_set_system_time(t)) // implemented in lwip2-sntp.c + +/* + -------------------------------------------------- + -------------------------------------------------- +*/ + +#include "lwip/debug.h" +#include "arch/cc.h" +#include "lwip-git-hash.h" + +#endif // MYLWIPOPTS_H diff --git a/tools/sdk/lwip2/include/netif/etharp.h b/tools/sdk/lwip2/include/netif/etharp.h new file mode 100644 index 000000000..b536fd280 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/netif/ethernet.h b/tools/sdk/lwip2/include/netif/ethernet.h new file mode 100644 index 000000000..49649cbf8 --- /dev/null +++ b/tools/sdk/lwip2/include/netif/ethernet.h @@ -0,0 +1,77 @@ +/** + * @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" + +#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); + +extern const struct eth_addr ethbroadcast, ethzero; + +#endif /* LWIP_ARP || LWIP_ETHERNET */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_NETIF_ETHERNET_H */ diff --git a/tools/sdk/lwip2/include/netif/lowpan6.h b/tools/sdk/lwip2/include/netif/lowpan6.h new file mode 100644 index 000000000..4174644bb --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/netif/lowpan6_opts.h b/tools/sdk/lwip2/include/netif/lowpan6_opts.h new file mode 100644 index 000000000..fb93ea05d --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/netif/ppp/ccp.h b/tools/sdk/lwip2/include/netif/ppp/ccp.h new file mode 100644 index 000000000..14dd65962 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/netif/ppp/chap-md5.h b/tools/sdk/lwip2/include/netif/ppp/chap-md5.h new file mode 100644 index 000000000..eb0269fe5 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/netif/ppp/chap-new.h b/tools/sdk/lwip2/include/netif/ppp/chap-new.h new file mode 100644 index 000000000..64eae3220 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/netif/ppp/chap_ms.h b/tools/sdk/lwip2/include/netif/ppp/chap_ms.h new file mode 100644 index 000000000..079529115 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/netif/ppp/eap.h b/tools/sdk/lwip2/include/netif/ppp/eap.h new file mode 100644 index 000000000..3ee9aaf81 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/netif/ppp/ecp.h b/tools/sdk/lwip2/include/netif/ppp/ecp.h new file mode 100644 index 000000000..5cdce29d5 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/netif/ppp/eui64.h b/tools/sdk/lwip2/include/netif/ppp/eui64.h new file mode 100644 index 000000000..20ac22eed --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/netif/ppp/fsm.h b/tools/sdk/lwip2/include/netif/ppp/fsm.h new file mode 100644 index 000000000..b6915d3b8 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/netif/ppp/ipcp.h b/tools/sdk/lwip2/include/netif/ppp/ipcp.h new file mode 100644 index 000000000..45f46b31f --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/netif/ppp/ipv6cp.h b/tools/sdk/lwip2/include/netif/ppp/ipv6cp.h new file mode 100644 index 000000000..07d1ae318 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/netif/ppp/lcp.h b/tools/sdk/lwip2/include/netif/ppp/lcp.h new file mode 100644 index 000000000..12e2a05fc --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/netif/ppp/magic.h b/tools/sdk/lwip2/include/netif/ppp/magic.h new file mode 100644 index 000000000..a2a9b530e --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/netif/ppp/mppe.h b/tools/sdk/lwip2/include/netif/ppp/mppe.h new file mode 100644 index 000000000..1ae8a5d92 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/netif/ppp/polarssl/arc4.h b/tools/sdk/lwip2/include/netif/ppp/polarssl/arc4.h new file mode 100644 index 000000000..4af724cd9 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/netif/ppp/polarssl/des.h b/tools/sdk/lwip2/include/netif/ppp/polarssl/des.h new file mode 100644 index 000000000..e893890ed --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/netif/ppp/polarssl/md4.h b/tools/sdk/lwip2/include/netif/ppp/polarssl/md4.h new file mode 100644 index 000000000..570445687 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/netif/ppp/polarssl/md5.h b/tools/sdk/lwip2/include/netif/ppp/polarssl/md5.h new file mode 100644 index 000000000..124401189 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/netif/ppp/polarssl/sha1.h b/tools/sdk/lwip2/include/netif/ppp/polarssl/sha1.h new file mode 100644 index 000000000..a4c53e07c --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/netif/ppp/ppp.h b/tools/sdk/lwip2/include/netif/ppp/ppp.h new file mode 100644 index 000000000..d9ea097ef --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/netif/ppp/ppp_impl.h b/tools/sdk/lwip2/include/netif/ppp/ppp_impl.h new file mode 100644 index 000000000..1d4c7742f --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/netif/ppp/ppp_opts.h b/tools/sdk/lwip2/include/netif/ppp/ppp_opts.h new file mode 100644 index 000000000..fa79c090f --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/netif/ppp/pppapi.h b/tools/sdk/lwip2/include/netif/ppp/pppapi.h new file mode 100644 index 000000000..913d93f74 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/netif/ppp/pppcrypt.h b/tools/sdk/lwip2/include/netif/ppp/pppcrypt.h new file mode 100644 index 000000000..a7b2099f2 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/netif/ppp/pppdebug.h b/tools/sdk/lwip2/include/netif/ppp/pppdebug.h new file mode 100644 index 000000000..7ead04591 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/netif/ppp/pppoe.h b/tools/sdk/lwip2/include/netif/ppp/pppoe.h new file mode 100644 index 000000000..9f8f2892b --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/netif/ppp/pppol2tp.h b/tools/sdk/lwip2/include/netif/ppp/pppol2tp.h new file mode 100644 index 000000000..f03950e65 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/netif/ppp/pppos.h b/tools/sdk/lwip2/include/netif/ppp/pppos.h new file mode 100644 index 000000000..d924a9fc7 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/netif/ppp/upap.h b/tools/sdk/lwip2/include/netif/ppp/upap.h new file mode 100644 index 000000000..7da792ecc --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/netif/ppp/vj.h b/tools/sdk/lwip2/include/netif/ppp/vj.h new file mode 100644 index 000000000..7f389c846 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/netif/slipif.h b/tools/sdk/lwip2/include/netif/slipif.h new file mode 100644 index 000000000..65ba31f83 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/posix/errno.h b/tools/sdk/lwip2/include/posix/errno.h new file mode 100644 index 000000000..5917c75e2 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/posix/netdb.h b/tools/sdk/lwip2/include/posix/netdb.h new file mode 100644 index 000000000..12d4c7f56 --- /dev/null +++ b/tools/sdk/lwip2/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/tools/sdk/lwip2/include/posix/sys/socket.h b/tools/sdk/lwip2/include/posix/sys/socket.h new file mode 100644 index 000000000..0ed9baf3d --- /dev/null +++ b/tools/sdk/lwip2/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"