sockets.c 93 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828
  1. /**
  2. * @file
  3. * Sockets BSD-Like API module
  4. *
  5. * @defgroup socket Socket API
  6. * @ingroup sequential_api
  7. * BSD-style socket API.\n
  8. * Thread-safe, to be called from non-TCPIP threads only.\n
  9. * Can be activated by defining @ref LWIP_SOCKET to 1.\n
  10. * Header is in posix/sys/socket.h\b
  11. */
  12. /*
  13. * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
  14. * All rights reserved.
  15. *
  16. * Redistribution and use in source and binary forms, with or without modification,
  17. * are permitted provided that the following conditions are met:
  18. *
  19. * 1. Redistributions of source code must retain the above copyright notice,
  20. * this list of conditions and the following disclaimer.
  21. * 2. Redistributions in binary form must reproduce the above copyright notice,
  22. * this list of conditions and the following disclaimer in the documentation
  23. * and/or other materials provided with the distribution.
  24. * 3. The name of the author may not be used to endorse or promote products
  25. * derived from this software without specific prior written permission.
  26. *
  27. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
  28. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  29. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
  30. * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  31. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
  32. * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  33. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  34. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  35. * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  36. * OF SUCH DAMAGE.
  37. *
  38. * This file is part of the lwIP TCP/IP stack.
  39. *
  40. * Author: Adam Dunkels <adam@sics.se>
  41. *
  42. * Improved by Marc Boucher <marc@mbsi.ca> and David Haas <dhaas@alum.rpi.edu>
  43. *
  44. */
  45. #include "lwip/opt.h"
  46. #if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */
  47. #include "lwip/sockets.h"
  48. #include "lwip/api.h"
  49. #include "lwip/sys.h"
  50. #include "lwip/igmp.h"
  51. #include "lwip/inet.h"
  52. #include "lwip/tcp.h"
  53. #include "lwip/raw.h"
  54. #include "lwip/udp.h"
  55. #include "lwip/memp.h"
  56. #include "lwip/pbuf.h"
  57. #include "lwip/priv/tcpip_priv.h"
  58. #if LWIP_CHECKSUM_ON_COPY
  59. #include "lwip/inet_chksum.h"
  60. #endif
  61. #include <string.h>
  62. /* If the netconn API is not required publicly, then we include the necessary
  63. files here to get the implementation */
  64. #if !LWIP_NETCONN
  65. #undef LWIP_NETCONN
  66. #define LWIP_NETCONN 1
  67. #include "api_msg.c"
  68. #include "api_lib.c"
  69. #include "netbuf.c"
  70. #undef LWIP_NETCONN
  71. #define LWIP_NETCONN 0
  72. #endif
  73. #if LWIP_IPV4
  74. #define IP4ADDR_PORT_TO_SOCKADDR(sin, ipaddr, port) do { \
  75. (sin)->sin_len = sizeof(struct sockaddr_in); \
  76. (sin)->sin_family = AF_INET; \
  77. (sin)->sin_port = lwip_htons((port)); \
  78. inet_addr_from_ip4addr(&(sin)->sin_addr, ipaddr); \
  79. memset((sin)->sin_zero, 0, SIN_ZERO_LEN); }while(0)
  80. #define SOCKADDR4_TO_IP4ADDR_PORT(sin, ipaddr, port) do { \
  81. inet_addr_to_ip4addr(ip_2_ip4(ipaddr), &((sin)->sin_addr)); \
  82. (port) = lwip_ntohs((sin)->sin_port); }while(0)
  83. #endif /* LWIP_IPV4 */
  84. #if LWIP_IPV6
  85. #define IP6ADDR_PORT_TO_SOCKADDR(sin6, ipaddr, port) do { \
  86. (sin6)->sin6_len = sizeof(struct sockaddr_in6); \
  87. (sin6)->sin6_family = AF_INET6; \
  88. (sin6)->sin6_port = lwip_htons((port)); \
  89. (sin6)->sin6_flowinfo = 0; \
  90. inet6_addr_from_ip6addr(&(sin6)->sin6_addr, ipaddr); \
  91. (sin6)->sin6_scope_id = 0; }while(0)
  92. #define SOCKADDR6_TO_IP6ADDR_PORT(sin6, ipaddr, port) do { \
  93. inet6_addr_to_ip6addr(ip_2_ip6(ipaddr), &((sin6)->sin6_addr)); \
  94. (port) = lwip_ntohs((sin6)->sin6_port); }while(0)
  95. #endif /* LWIP_IPV6 */
  96. #if LWIP_IPV4 && LWIP_IPV6
  97. static void sockaddr_to_ipaddr_port(const struct sockaddr* sockaddr, ip_addr_t* ipaddr, u16_t* port);
  98. #define IS_SOCK_ADDR_LEN_VALID(namelen) (((namelen) == sizeof(struct sockaddr_in)) || \
  99. ((namelen) == sizeof(struct sockaddr_in6)))
  100. #define IS_SOCK_ADDR_TYPE_VALID(name) (((name)->sa_family == AF_INET) || \
  101. ((name)->sa_family == AF_INET6))
  102. #define SOCK_ADDR_TYPE_MATCH(name, sock) \
  103. ((((name)->sa_family == AF_INET) && !(NETCONNTYPE_ISIPV6((sock)->conn->type))) || \
  104. (((name)->sa_family == AF_INET6) && (NETCONNTYPE_ISIPV6((sock)->conn->type))))
  105. #define IPADDR_PORT_TO_SOCKADDR(sockaddr, ipaddr, port) do { \
  106. if (IP_IS_V6(ipaddr)) { \
  107. IP6ADDR_PORT_TO_SOCKADDR((struct sockaddr_in6*)(void*)(sockaddr), ip_2_ip6(ipaddr), port); \
  108. } else { \
  109. IP4ADDR_PORT_TO_SOCKADDR((struct sockaddr_in*)(void*)(sockaddr), ip_2_ip4(ipaddr), port); \
  110. } } while(0)
  111. #define SOCKADDR_TO_IPADDR_PORT(sockaddr, ipaddr, port) sockaddr_to_ipaddr_port(sockaddr, ipaddr, &(port))
  112. #define DOMAIN_TO_NETCONN_TYPE(domain, type) (((domain) == AF_INET) ? \
  113. (type) : (enum netconn_type)((type) | NETCONN_TYPE_IPV6))
  114. #elif LWIP_IPV6 /* LWIP_IPV4 && LWIP_IPV6 */
  115. #define IS_SOCK_ADDR_LEN_VALID(namelen) ((namelen) == sizeof(struct sockaddr_in6))
  116. #define IS_SOCK_ADDR_TYPE_VALID(name) ((name)->sa_family == AF_INET6)
  117. #define SOCK_ADDR_TYPE_MATCH(name, sock) 1
  118. #define IPADDR_PORT_TO_SOCKADDR(sockaddr, ipaddr, port) \
  119. IP6ADDR_PORT_TO_SOCKADDR((struct sockaddr_in6*)(void*)(sockaddr), ip_2_ip6(ipaddr), port)
  120. #define SOCKADDR_TO_IPADDR_PORT(sockaddr, ipaddr, port) \
  121. SOCKADDR6_TO_IP6ADDR_PORT((const struct sockaddr_in6*)(const void*)(sockaddr), ipaddr, port)
  122. #define DOMAIN_TO_NETCONN_TYPE(domain, netconn_type) (netconn_type)
  123. #else /*-> LWIP_IPV4: LWIP_IPV4 && LWIP_IPV6 */
  124. #define IS_SOCK_ADDR_LEN_VALID(namelen) ((namelen) == sizeof(struct sockaddr_in))
  125. #define IS_SOCK_ADDR_TYPE_VALID(name) ((name)->sa_family == AF_INET)
  126. #define SOCK_ADDR_TYPE_MATCH(name, sock) 1
  127. #define IPADDR_PORT_TO_SOCKADDR(sockaddr, ipaddr, port) \
  128. IP4ADDR_PORT_TO_SOCKADDR((struct sockaddr_in*)(void*)(sockaddr), ip_2_ip4(ipaddr), port)
  129. #define SOCKADDR_TO_IPADDR_PORT(sockaddr, ipaddr, port) \
  130. SOCKADDR4_TO_IP4ADDR_PORT((const struct sockaddr_in*)(const void*)(sockaddr), ipaddr, port)
  131. #define DOMAIN_TO_NETCONN_TYPE(domain, netconn_type) (netconn_type)
  132. #endif /* LWIP_IPV6 */
  133. #define IS_SOCK_ADDR_TYPE_VALID_OR_UNSPEC(name) (((name)->sa_family == AF_UNSPEC) || \
  134. IS_SOCK_ADDR_TYPE_VALID(name))
  135. #define SOCK_ADDR_TYPE_MATCH_OR_UNSPEC(name, sock) (((name)->sa_family == AF_UNSPEC) || \
  136. SOCK_ADDR_TYPE_MATCH(name, sock))
  137. #define IS_SOCK_ADDR_ALIGNED(name) ((((mem_ptr_t)(name)) % 4) == 0)
  138. #define LWIP_SOCKOPT_CHECK_OPTLEN(optlen, opttype) do { if ((optlen) < sizeof(opttype)) { return EINVAL; }}while(0)
  139. #define LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, opttype) do { \
  140. LWIP_SOCKOPT_CHECK_OPTLEN(optlen, opttype); \
  141. if ((sock)->conn == NULL) { return EINVAL; } }while(0)
  142. #define LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, opttype) do { \
  143. LWIP_SOCKOPT_CHECK_OPTLEN(optlen, opttype); \
  144. if (((sock)->conn == NULL) || ((sock)->conn->pcb.tcp == NULL)) { return EINVAL; } }while(0)
  145. #define LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, opttype, netconntype) do { \
  146. LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, opttype); \
  147. if (NETCONNTYPE_GROUP(netconn_type((sock)->conn)) != netconntype) { return ENOPROTOOPT; } }while(0)
  148. #define LWIP_SETGETSOCKOPT_DATA_VAR_REF(name) API_VAR_REF(name)
  149. #define LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(name) API_VAR_DECLARE(struct lwip_setgetsockopt_data, name)
  150. #define LWIP_SETGETSOCKOPT_DATA_VAR_FREE(name) API_VAR_FREE(MEMP_SOCKET_SETGETSOCKOPT_DATA, name)
  151. #if LWIP_MPU_COMPATIBLE
  152. #define LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(name, sock) do { \
  153. name = (struct lwip_setgetsockopt_data *)memp_malloc(MEMP_SOCKET_SETGETSOCKOPT_DATA); \
  154. if (name == NULL) { \
  155. sock_set_errno(sock, ENOMEM); \
  156. return -1; \
  157. } }while(0)
  158. #else /* LWIP_MPU_COMPATIBLE */
  159. #define LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(name, sock)
  160. #endif /* LWIP_MPU_COMPATIBLE */
  161. #if LWIP_SO_SNDRCVTIMEO_NONSTANDARD
  162. #define LWIP_SO_SNDRCVTIMEO_OPTTYPE int
  163. #define LWIP_SO_SNDRCVTIMEO_SET(optval, val) (*(int *)(optval) = (val))
  164. #define LWIP_SO_SNDRCVTIMEO_GET_MS(optval) ((s32_t)*(const int*)(optval))
  165. #else
  166. #define LWIP_SO_SNDRCVTIMEO_OPTTYPE struct timeval
  167. #define LWIP_SO_SNDRCVTIMEO_SET(optval, val) do { \
  168. s32_t loc = (val); \
  169. ((struct timeval *)(optval))->tv_sec = (loc) / 1000U; \
  170. ((struct timeval *)(optval))->tv_usec = ((loc) % 1000U) * 1000U; }while(0)
  171. #define LWIP_SO_SNDRCVTIMEO_GET_MS(optval) ((((const struct timeval *)(optval))->tv_sec * 1000U) + (((const struct timeval *)(optval))->tv_usec / 1000U))
  172. #endif
  173. #define NUM_SOCKETS MEMP_NUM_NETCONN
  174. /** This is overridable for the rare case where more than 255 threads
  175. * select on the same socket...
  176. */
  177. #ifndef SELWAIT_T
  178. #define SELWAIT_T u8_t
  179. #endif
  180. /** Contains all internal pointers and states used for a socket */
  181. struct lwip_sock {
  182. /** sockets currently are built on netconns, each socket has one netconn */
  183. struct netconn *conn;
  184. /** data that was left from the previous read */
  185. void *lastdata;
  186. /** offset in the data that was left from the previous read */
  187. u16_t lastoffset;
  188. /** number of times data was received, set by event_callback(),
  189. tested by the receive and select functions */
  190. s16_t rcvevent;
  191. /** number of times data was ACKed (free send buffer), set by event_callback(),
  192. tested by select */
  193. u16_t sendevent;
  194. /** error happened for this socket, set by event_callback(), tested by select */
  195. u16_t errevent;
  196. /** last error that occurred on this socket (in fact, all our errnos fit into an u8_t) */
  197. u8_t err;
  198. /** counter of how many threads are waiting for this socket using select */
  199. SELWAIT_T select_waiting;
  200. };
  201. #if LWIP_NETCONN_SEM_PER_THREAD
  202. #define SELECT_SEM_T sys_sem_t*
  203. #define SELECT_SEM_PTR(sem) (sem)
  204. #else /* LWIP_NETCONN_SEM_PER_THREAD */
  205. #define SELECT_SEM_T sys_sem_t
  206. #define SELECT_SEM_PTR(sem) (&(sem))
  207. #endif /* LWIP_NETCONN_SEM_PER_THREAD */
  208. /** Description for a task waiting in select */
  209. struct lwip_select_cb {
  210. /** Pointer to the next waiting task */
  211. struct lwip_select_cb *next;
  212. /** Pointer to the previous waiting task */
  213. struct lwip_select_cb *prev;
  214. /** readset passed to select */
  215. fd_set *readset;
  216. /** writeset passed to select */
  217. fd_set *writeset;
  218. /** unimplemented: exceptset passed to select */
  219. fd_set *exceptset;
  220. /** don't signal the same semaphore twice: set to 1 when signalled */
  221. int sem_signalled;
  222. /** semaphore to wake up a task waiting for select */
  223. SELECT_SEM_T sem;
  224. };
  225. /** A struct sockaddr replacement that has the same alignment as sockaddr_in/
  226. * sockaddr_in6 if instantiated.
  227. */
  228. union sockaddr_aligned {
  229. struct sockaddr sa;
  230. #if LWIP_IPV6
  231. struct sockaddr_in6 sin6;
  232. #endif /* LWIP_IPV6 */
  233. #if LWIP_IPV4
  234. struct sockaddr_in sin;
  235. #endif /* LWIP_IPV4 */
  236. };
  237. #if LWIP_IGMP
  238. /* Define the number of IPv4 multicast memberships, default is one per socket */
  239. #ifndef LWIP_SOCKET_MAX_MEMBERSHIPS
  240. #define LWIP_SOCKET_MAX_MEMBERSHIPS NUM_SOCKETS
  241. #endif
  242. /* This is to keep track of IP_ADD_MEMBERSHIP calls to drop the membership when
  243. a socket is closed */
  244. struct lwip_socket_multicast_pair {
  245. /** the socket */
  246. struct lwip_sock* sock;
  247. /** the interface address */
  248. ip4_addr_t if_addr;
  249. /** the group address */
  250. ip4_addr_t multi_addr;
  251. };
  252. struct lwip_socket_multicast_pair socket_ipv4_multicast_memberships[LWIP_SOCKET_MAX_MEMBERSHIPS];
  253. static int lwip_socket_register_membership(int s, const ip4_addr_t *if_addr, const ip4_addr_t *multi_addr);
  254. static void lwip_socket_unregister_membership(int s, const ip4_addr_t *if_addr, const ip4_addr_t *multi_addr);
  255. static void lwip_socket_drop_registered_memberships(int s);
  256. #endif /* LWIP_IGMP */
  257. /** The global array of available sockets */
  258. static struct lwip_sock sockets[NUM_SOCKETS];
  259. /** The global list of tasks waiting for select */
  260. static struct lwip_select_cb *select_cb_list;
  261. /** This counter is increased from lwip_select when the list is changed
  262. and checked in event_callback to see if it has changed. */
  263. static volatile int select_cb_ctr;
  264. #if LWIP_SOCKET_SET_ERRNO
  265. #ifndef set_errno
  266. #define set_errno(err) do { if (err) { errno = (err); } } while(0)
  267. #endif
  268. #else /* LWIP_SOCKET_SET_ERRNO */
  269. #define set_errno(err)
  270. #endif /* LWIP_SOCKET_SET_ERRNO */
  271. #define sock_set_errno(sk, e) do { \
  272. const int sockerr = (e); \
  273. sk->err = (u8_t)sockerr; \
  274. set_errno(sockerr); \
  275. } while (0)
  276. /* Forward declaration of some functions */
  277. static void event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len);
  278. #if !LWIP_TCPIP_CORE_LOCKING
  279. static void lwip_getsockopt_callback(void *arg);
  280. static void lwip_setsockopt_callback(void *arg);
  281. #endif
  282. static u8_t lwip_getsockopt_impl(int s, int level, int optname, void *optval, socklen_t *optlen);
  283. static u8_t lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_t optlen);
  284. #if LWIP_IPV4 && LWIP_IPV6
  285. static void
  286. sockaddr_to_ipaddr_port(const struct sockaddr* sockaddr, ip_addr_t* ipaddr, u16_t* port)
  287. {
  288. if ((sockaddr->sa_family) == AF_INET6) {
  289. SOCKADDR6_TO_IP6ADDR_PORT((const struct sockaddr_in6*)(const void*)(sockaddr), ipaddr, *port);
  290. ipaddr->type = IPADDR_TYPE_V6;
  291. } else {
  292. SOCKADDR4_TO_IP4ADDR_PORT((const struct sockaddr_in*)(const void*)(sockaddr), ipaddr, *port);
  293. ipaddr->type = IPADDR_TYPE_V4;
  294. }
  295. }
  296. #endif /* LWIP_IPV4 && LWIP_IPV6 */
  297. /** LWIP_NETCONN_SEM_PER_THREAD==1: initialize thread-local semaphore */
  298. void
  299. lwip_socket_thread_init(void)
  300. {
  301. netconn_thread_init();
  302. }
  303. /** LWIP_NETCONN_SEM_PER_THREAD==1: destroy thread-local semaphore */
  304. void
  305. lwip_socket_thread_cleanup(void)
  306. {
  307. netconn_thread_cleanup();
  308. }
  309. /**
  310. * Map a externally used socket index to the internal socket representation.
  311. *
  312. * @param s externally used socket index
  313. * @return struct lwip_sock for the socket or NULL if not found
  314. */
  315. static struct lwip_sock *
  316. get_socket(int s)
  317. {
  318. struct lwip_sock *sock;
  319. s -= LWIP_SOCKET_OFFSET;
  320. if ((s < 0) || (s >= NUM_SOCKETS)) {
  321. LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): invalid\n", s + LWIP_SOCKET_OFFSET));
  322. set_errno(EBADF);
  323. return NULL;
  324. }
  325. sock = &sockets[s];
  326. if (!sock->conn) {
  327. LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): not active\n", s + LWIP_SOCKET_OFFSET));
  328. set_errno(EBADF);
  329. return NULL;
  330. }
  331. return sock;
  332. }
  333. /**
  334. * Same as get_socket but doesn't set errno
  335. *
  336. * @param s externally used socket index
  337. * @return struct lwip_sock for the socket or NULL if not found
  338. */
  339. static struct lwip_sock *
  340. tryget_socket(int s)
  341. {
  342. s -= LWIP_SOCKET_OFFSET;
  343. if ((s < 0) || (s >= NUM_SOCKETS)) {
  344. return NULL;
  345. }
  346. if (!sockets[s].conn) {
  347. return NULL;
  348. }
  349. return &sockets[s];
  350. }
  351. /**
  352. * Allocate a new socket for a given netconn.
  353. *
  354. * @param newconn the netconn for which to allocate a socket
  355. * @param accepted 1 if socket has been created by accept(),
  356. * 0 if socket has been created by socket()
  357. * @return the index of the new socket; -1 on error
  358. */
  359. static int
  360. alloc_socket(struct netconn *newconn, int accepted)
  361. {
  362. int i;
  363. SYS_ARCH_DECL_PROTECT(lev);
  364. /* allocate a new socket identifier */
  365. for (i = 0; i < NUM_SOCKETS; ++i) {
  366. /* Protect socket array */
  367. SYS_ARCH_PROTECT(lev);
  368. if (!sockets[i].conn && (sockets[i].select_waiting == 0)) {
  369. sockets[i].conn = newconn;
  370. /* The socket is not yet known to anyone, so no need to protect
  371. after having marked it as used. */
  372. SYS_ARCH_UNPROTECT(lev);
  373. sockets[i].lastdata = NULL;
  374. sockets[i].lastoffset = 0;
  375. sockets[i].rcvevent = 0;
  376. /* TCP sendbuf is empty, but the socket is not yet writable until connected
  377. * (unless it has been created by accept()). */
  378. sockets[i].sendevent = (NETCONNTYPE_GROUP(newconn->type) == NETCONN_TCP ? (accepted != 0) : 1);
  379. sockets[i].errevent = 0;
  380. sockets[i].err = 0;
  381. return i + LWIP_SOCKET_OFFSET;
  382. }
  383. SYS_ARCH_UNPROTECT(lev);
  384. }
  385. return -1;
  386. }
  387. /** Free a socket. The socket's netconn must have been
  388. * delete before!
  389. *
  390. * @param sock the socket to free
  391. * @param is_tcp != 0 for TCP sockets, used to free lastdata
  392. */
  393. static void
  394. free_socket(struct lwip_sock *sock, int is_tcp)
  395. {
  396. void *lastdata;
  397. lastdata = sock->lastdata;
  398. sock->lastdata = NULL;
  399. sock->lastoffset = 0;
  400. sock->err = 0;
  401. /* Protect socket array */
  402. SYS_ARCH_SET(sock->conn, NULL);
  403. /* don't use 'sock' after this line, as another task might have allocated it */
  404. if (lastdata != NULL) {
  405. if (is_tcp) {
  406. pbuf_free((struct pbuf *)lastdata);
  407. } else {
  408. netbuf_delete((struct netbuf *)lastdata);
  409. }
  410. }
  411. }
  412. /* Below this, the well-known socket functions are implemented.
  413. * Use google.com or opengroup.org to get a good description :-)
  414. *
  415. * Exceptions are documented!
  416. */
  417. int
  418. lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
  419. {
  420. struct lwip_sock *sock, *nsock;
  421. struct netconn *newconn;
  422. ip_addr_t naddr;
  423. u16_t port = 0;
  424. int newsock;
  425. err_t err;
  426. SYS_ARCH_DECL_PROTECT(lev);
  427. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d)...\n", s));
  428. sock = get_socket(s);
  429. if (!sock) {
  430. return -1;
  431. }
  432. if (netconn_is_nonblocking(sock->conn) && (sock->rcvevent <= 0)) {
  433. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): returning EWOULDBLOCK\n", s));
  434. set_errno(EWOULDBLOCK);
  435. return -1;
  436. }
  437. /* wait for a new connection */
  438. err = netconn_accept(sock->conn, &newconn);
  439. if (err != ERR_OK) {
  440. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): netconn_acept failed, err=%d\n", s, err));
  441. if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) {
  442. sock_set_errno(sock, EOPNOTSUPP);
  443. } else if (err == ERR_CLSD) {
  444. sock_set_errno(sock, EINVAL);
  445. } else {
  446. sock_set_errno(sock, err_to_errno(err));
  447. }
  448. return -1;
  449. }
  450. LWIP_ASSERT("newconn != NULL", newconn != NULL);
  451. newsock = alloc_socket(newconn, 1);
  452. if (newsock == -1) {
  453. netconn_delete(newconn);
  454. sock_set_errno(sock, ENFILE);
  455. return -1;
  456. }
  457. LWIP_ASSERT("invalid socket index", (newsock >= LWIP_SOCKET_OFFSET) && (newsock < NUM_SOCKETS + LWIP_SOCKET_OFFSET));
  458. LWIP_ASSERT("newconn->callback == event_callback", newconn->callback == event_callback);
  459. nsock = &sockets[newsock - LWIP_SOCKET_OFFSET];
  460. /* See event_callback: If data comes in right away after an accept, even
  461. * though the server task might not have created a new socket yet.
  462. * In that case, newconn->socket is counted down (newconn->socket--),
  463. * so nsock->rcvevent is >= 1 here!
  464. */
  465. SYS_ARCH_PROTECT(lev);
  466. nsock->rcvevent += (s16_t)(-1 - newconn->socket);
  467. newconn->socket = newsock;
  468. SYS_ARCH_UNPROTECT(lev);
  469. /* Note that POSIX only requires us to check addr is non-NULL. addrlen must
  470. * not be NULL if addr is valid.
  471. */
  472. if (addr != NULL) {
  473. union sockaddr_aligned tempaddr;
  474. /* get the IP address and port of the remote host */
  475. err = netconn_peer(newconn, &naddr, &port);
  476. if (err != ERR_OK) {
  477. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): netconn_peer failed, err=%d\n", s, err));
  478. netconn_delete(newconn);
  479. free_socket(nsock, 1);
  480. sock_set_errno(sock, err_to_errno(err));
  481. return -1;
  482. }
  483. LWIP_ASSERT("addr valid but addrlen NULL", addrlen != NULL);
  484. IPADDR_PORT_TO_SOCKADDR(&tempaddr, &naddr, port);
  485. if (*addrlen > tempaddr.sa.sa_len) {
  486. *addrlen = tempaddr.sa.sa_len;
  487. }
  488. MEMCPY(addr, &tempaddr, *addrlen);
  489. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d addr=", s, newsock));
  490. ip_addr_debug_print_val(SOCKETS_DEBUG, naddr);
  491. LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", port));
  492. } else {
  493. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d", s, newsock));
  494. }
  495. sock_set_errno(sock, 0);
  496. return newsock;
  497. }
  498. int
  499. lwip_bind(int s, const struct sockaddr *name, socklen_t namelen)
  500. {
  501. struct lwip_sock *sock;
  502. ip_addr_t local_addr;
  503. u16_t local_port;
  504. err_t err;
  505. sock = get_socket(s);
  506. if (!sock) {
  507. return -1;
  508. }
  509. if (!SOCK_ADDR_TYPE_MATCH(name, sock)) {
  510. /* sockaddr does not match socket type (IPv4/IPv6) */
  511. sock_set_errno(sock, err_to_errno(ERR_VAL));
  512. return -1;
  513. }
  514. /* check size, family and alignment of 'name' */
  515. LWIP_ERROR("lwip_bind: invalid address", (IS_SOCK_ADDR_LEN_VALID(namelen) &&
  516. IS_SOCK_ADDR_TYPE_VALID(name) && IS_SOCK_ADDR_ALIGNED(name)),
  517. sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
  518. LWIP_UNUSED_ARG(namelen);
  519. SOCKADDR_TO_IPADDR_PORT(name, &local_addr, local_port);
  520. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s));
  521. ip_addr_debug_print_val(SOCKETS_DEBUG, local_addr);
  522. LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", local_port));
  523. #if LWIP_IPV4 && LWIP_IPV6
  524. /* Dual-stack: Unmap IPv4 mapped IPv6 addresses */
  525. if (IP_IS_V6_VAL(local_addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(&local_addr))) {
  526. unmap_ipv4_mapped_ipv6(ip_2_ip4(&local_addr), ip_2_ip6(&local_addr));
  527. IP_SET_TYPE_VAL(local_addr, IPADDR_TYPE_V4);
  528. }
  529. #endif /* LWIP_IPV4 && LWIP_IPV6 */
  530. err = netconn_bind(sock->conn, &local_addr, local_port);
  531. if (err != ERR_OK) {
  532. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) failed, err=%d\n", s, err));
  533. sock_set_errno(sock, err_to_errno(err));
  534. return -1;
  535. }
  536. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) succeeded\n", s));
  537. sock_set_errno(sock, 0);
  538. return 0;
  539. }
  540. int
  541. lwip_close(int s)
  542. {
  543. struct lwip_sock *sock;
  544. int is_tcp = 0;
  545. err_t err;
  546. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_close(%d)\n", s));
  547. sock = get_socket(s);
  548. if (!sock) {
  549. return -1;
  550. }
  551. if (sock->conn != NULL) {
  552. is_tcp = NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP;
  553. } else {
  554. LWIP_ASSERT("sock->lastdata == NULL", sock->lastdata == NULL);
  555. }
  556. #if LWIP_IGMP
  557. /* drop all possibly joined IGMP memberships */
  558. lwip_socket_drop_registered_memberships(s);
  559. #endif /* LWIP_IGMP */
  560. err = netconn_delete(sock->conn);
  561. if (err != ERR_OK) {
  562. sock_set_errno(sock, err_to_errno(err));
  563. return -1;
  564. }
  565. free_socket(sock, is_tcp);
  566. set_errno(0);
  567. return 0;
  568. }
  569. int
  570. lwip_connect(int s, const struct sockaddr *name, socklen_t namelen)
  571. {
  572. struct lwip_sock *sock;
  573. err_t err;
  574. sock = get_socket(s);
  575. if (!sock) {
  576. return -1;
  577. }
  578. if (!SOCK_ADDR_TYPE_MATCH_OR_UNSPEC(name, sock)) {
  579. /* sockaddr does not match socket type (IPv4/IPv6) */
  580. sock_set_errno(sock, err_to_errno(ERR_VAL));
  581. return -1;
  582. }
  583. LWIP_UNUSED_ARG(namelen);
  584. if (name->sa_family == AF_UNSPEC) {
  585. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, AF_UNSPEC)\n", s));
  586. err = netconn_disconnect(sock->conn);
  587. } else {
  588. ip_addr_t remote_addr;
  589. u16_t remote_port;
  590. /* check size, family and alignment of 'name' */
  591. LWIP_ERROR("lwip_connect: invalid address", IS_SOCK_ADDR_LEN_VALID(namelen) &&
  592. IS_SOCK_ADDR_TYPE_VALID_OR_UNSPEC(name) && IS_SOCK_ADDR_ALIGNED(name),
  593. sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
  594. SOCKADDR_TO_IPADDR_PORT(name, &remote_addr, remote_port);
  595. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, addr=", s));
  596. ip_addr_debug_print_val(SOCKETS_DEBUG, remote_addr);
  597. LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", remote_port));
  598. #if LWIP_IPV4 && LWIP_IPV6
  599. /* Dual-stack: Unmap IPv4 mapped IPv6 addresses */
  600. if (IP_IS_V6_VAL(remote_addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(&remote_addr))) {
  601. unmap_ipv4_mapped_ipv6(ip_2_ip4(&remote_addr), ip_2_ip6(&remote_addr));
  602. IP_SET_TYPE_VAL(remote_addr, IPADDR_TYPE_V4);
  603. }
  604. #endif /* LWIP_IPV4 && LWIP_IPV6 */
  605. err = netconn_connect(sock->conn, &remote_addr, remote_port);
  606. }
  607. if (err != ERR_OK) {
  608. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) failed, err=%d\n", s, err));
  609. sock_set_errno(sock, err_to_errno(err));
  610. return -1;
  611. }
  612. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) succeeded\n", s));
  613. sock_set_errno(sock, 0);
  614. return 0;
  615. }
  616. /**
  617. * Set a socket into listen mode.
  618. * The socket may not have been used for another connection previously.
  619. *
  620. * @param s the socket to set to listening mode
  621. * @param backlog (ATTENTION: needs TCP_LISTEN_BACKLOG=1)
  622. * @return 0 on success, non-zero on failure
  623. */
  624. int
  625. lwip_listen(int s, int backlog)
  626. {
  627. struct lwip_sock *sock;
  628. err_t err;
  629. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d, backlog=%d)\n", s, backlog));
  630. sock = get_socket(s);
  631. if (!sock) {
  632. return -1;
  633. }
  634. /* limit the "backlog" parameter to fit in an u8_t */
  635. backlog = LWIP_MIN(LWIP_MAX(backlog, 0), 0xff);
  636. err = netconn_listen_with_backlog(sock->conn, (u8_t)backlog);
  637. if (err != ERR_OK) {
  638. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d) failed, err=%d\n", s, err));
  639. if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) {
  640. sock_set_errno(sock, EOPNOTSUPP);
  641. return -1;
  642. }
  643. sock_set_errno(sock, err_to_errno(err));
  644. return -1;
  645. }
  646. sock_set_errno(sock, 0);
  647. return 0;
  648. }
  649. int
  650. lwip_recvfrom(int s, void *mem, size_t len, int flags,
  651. struct sockaddr *from, socklen_t *fromlen)
  652. {
  653. struct lwip_sock *sock;
  654. void *buf = NULL;
  655. struct pbuf *p;
  656. u16_t buflen, copylen;
  657. int off = 0;
  658. u8_t done = 0;
  659. err_t err;
  660. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d, %p, %"SZT_F", 0x%x, ..)\n", s, mem, len, flags));
  661. sock = get_socket(s);
  662. if (!sock) {
  663. return -1;
  664. }
  665. do {
  666. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: top while sock->lastdata=%p\n", sock->lastdata));
  667. /* Check if there is data left from the last recv operation. */
  668. if (sock->lastdata) {
  669. buf = sock->lastdata;
  670. } else {
  671. /* If this is non-blocking call, then check first */
  672. if (((flags & MSG_DONTWAIT) || netconn_is_nonblocking(sock->conn)) &&
  673. (sock->rcvevent <= 0)) {
  674. if (off > 0) {
  675. /* already received data, return that */
  676. sock_set_errno(sock, 0);
  677. return off;
  678. }
  679. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): returning EWOULDBLOCK\n", s));
  680. set_errno(EWOULDBLOCK);
  681. return -1;
  682. }
  683. /* No data was left from the previous operation, so we try to get
  684. some from the network. */
  685. if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
  686. err = netconn_recv_tcp_pbuf(sock->conn, (struct pbuf **)&buf);
  687. } else {
  688. err = netconn_recv(sock->conn, (struct netbuf **)&buf);
  689. }
  690. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: netconn_recv err=%d, netbuf=%p\n",
  691. err, buf));
  692. if (err != ERR_OK) {
  693. if (off > 0) {
  694. if (err == ERR_CLSD) {
  695. /* closed but already received data, ensure select gets the FIN, too */
  696. event_callback(sock->conn, NETCONN_EVT_RCVPLUS, 0);
  697. }
  698. /* already received data, return that */
  699. sock_set_errno(sock, 0);
  700. return off;
  701. }
  702. /* We should really do some error checking here. */
  703. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): buf == NULL, error is \"%s\"!\n",
  704. s, lwip_strerr(err)));
  705. sock_set_errno(sock, err_to_errno(err));
  706. if (err == ERR_CLSD) {
  707. return 0;
  708. } else {
  709. return -1;
  710. }
  711. }
  712. LWIP_ASSERT("buf != NULL", buf != NULL);
  713. sock->lastdata = buf;
  714. }
  715. if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
  716. p = (struct pbuf *)buf;
  717. } else {
  718. p = ((struct netbuf *)buf)->p;
  719. }
  720. buflen = p->tot_len;
  721. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: buflen=%"U16_F" len=%"SZT_F" off=%d sock->lastoffset=%"U16_F"\n",
  722. buflen, len, off, sock->lastoffset));
  723. buflen -= sock->lastoffset;
  724. if (len > buflen) {
  725. copylen = buflen;
  726. } else {
  727. copylen = (u16_t)len;
  728. }
  729. /* copy the contents of the received buffer into
  730. the supplied memory pointer mem */
  731. pbuf_copy_partial(p, (u8_t*)mem + off, copylen, sock->lastoffset);
  732. off += copylen;
  733. if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
  734. LWIP_ASSERT("invalid copylen, len would underflow", len >= copylen);
  735. len -= copylen;
  736. if ((len <= 0) ||
  737. (p->flags & PBUF_FLAG_PUSH) ||
  738. (sock->rcvevent <= 0) ||
  739. ((flags & MSG_PEEK) != 0)) {
  740. done = 1;
  741. }
  742. } else {
  743. done = 1;
  744. }
  745. /* Check to see from where the data was.*/
  746. if (done) {
  747. #if !SOCKETS_DEBUG
  748. if (from && fromlen)
  749. #endif /* !SOCKETS_DEBUG */
  750. {
  751. u16_t port;
  752. ip_addr_t tmpaddr;
  753. ip_addr_t *fromaddr;
  754. union sockaddr_aligned saddr;
  755. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s));
  756. if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
  757. fromaddr = &tmpaddr;
  758. netconn_getaddr(sock->conn, fromaddr, &port, 0);
  759. } else {
  760. port = netbuf_fromport((struct netbuf *)buf);
  761. fromaddr = netbuf_fromaddr((struct netbuf *)buf);
  762. }
  763. #if LWIP_IPV4 && LWIP_IPV6
  764. /* Dual-stack: Map IPv4 addresses to IPv4 mapped IPv6 */
  765. if (NETCONNTYPE_ISIPV6(netconn_type(sock->conn)) && IP_IS_V4(fromaddr)) {
  766. ip4_2_ipv4_mapped_ipv6(ip_2_ip6(fromaddr), ip_2_ip4(fromaddr));
  767. IP_SET_TYPE(fromaddr, IPADDR_TYPE_V6);
  768. }
  769. #endif /* LWIP_IPV4 && LWIP_IPV6 */
  770. IPADDR_PORT_TO_SOCKADDR(&saddr, fromaddr, port);
  771. ip_addr_debug_print(SOCKETS_DEBUG, fromaddr);
  772. LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F" len=%d\n", port, off));
  773. #if SOCKETS_DEBUG
  774. if (from && fromlen)
  775. #endif /* SOCKETS_DEBUG */
  776. {
  777. if (*fromlen > saddr.sa.sa_len) {
  778. *fromlen = saddr.sa.sa_len;
  779. }
  780. MEMCPY(from, &saddr, *fromlen);
  781. }
  782. }
  783. }
  784. /* If we don't peek the incoming message... */
  785. if ((flags & MSG_PEEK) == 0) {
  786. /* If this is a TCP socket, check if there is data left in the
  787. buffer. If so, it should be saved in the sock structure for next
  788. time around. */
  789. if ((NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) && (buflen - copylen > 0)) {
  790. sock->lastdata = buf;
  791. sock->lastoffset += copylen;
  792. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: lastdata now netbuf=%p\n", buf));
  793. } else {
  794. sock->lastdata = NULL;
  795. sock->lastoffset = 0;
  796. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: deleting netbuf=%p\n", buf));
  797. if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
  798. pbuf_free((struct pbuf *)buf);
  799. } else {
  800. netbuf_delete((struct netbuf *)buf);
  801. }
  802. buf = NULL;
  803. }
  804. }
  805. } while (!done);
  806. sock_set_errno(sock, 0);
  807. return off;
  808. }
  809. int
  810. lwip_read(int s, void *mem, size_t len)
  811. {
  812. return lwip_recvfrom(s, mem, len, 0, NULL, NULL);
  813. }
  814. int
  815. lwip_recv(int s, void *mem, size_t len, int flags)
  816. {
  817. return lwip_recvfrom(s, mem, len, flags, NULL, NULL);
  818. }
  819. int
  820. lwip_send(int s, const void *data, size_t size, int flags)
  821. {
  822. struct lwip_sock *sock;
  823. err_t err;
  824. u8_t write_flags;
  825. size_t written;
  826. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d, data=%p, size=%"SZT_F", flags=0x%x)\n",
  827. s, data, size, flags));
  828. sock = get_socket(s);
  829. if (!sock) {
  830. return -1;
  831. }
  832. if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) {
  833. #if (LWIP_UDP || LWIP_RAW)
  834. return lwip_sendto(s, data, size, flags, NULL, 0);
  835. #else /* (LWIP_UDP || LWIP_RAW) */
  836. sock_set_errno(sock, err_to_errno(ERR_ARG));
  837. return -1;
  838. #endif /* (LWIP_UDP || LWIP_RAW) */
  839. }
  840. write_flags = NETCONN_COPY |
  841. ((flags & MSG_MORE) ? NETCONN_MORE : 0) |
  842. ((flags & MSG_DONTWAIT) ? NETCONN_DONTBLOCK : 0);
  843. written = 0;
  844. err = netconn_write_partly(sock->conn, data, size, write_flags, &written);
  845. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) err=%d written=%"SZT_F"\n", s, err, written));
  846. sock_set_errno(sock, err_to_errno(err));
  847. return (err == ERR_OK ? (int)written : -1);
  848. }
  849. int
  850. lwip_sendmsg(int s, const struct msghdr *msg, int flags)
  851. {
  852. struct lwip_sock *sock;
  853. int i;
  854. #if LWIP_TCP
  855. u8_t write_flags;
  856. size_t written;
  857. #endif
  858. int size = 0;
  859. err_t err = ERR_OK;
  860. sock = get_socket(s);
  861. if (!sock) {
  862. return -1;
  863. }
  864. LWIP_ERROR("lwip_sendmsg: invalid msghdr", msg != NULL,
  865. sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
  866. LWIP_UNUSED_ARG(msg->msg_control);
  867. LWIP_UNUSED_ARG(msg->msg_controllen);
  868. LWIP_UNUSED_ARG(msg->msg_flags);
  869. LWIP_ERROR("lwip_sendmsg: invalid msghdr iov", (msg->msg_iov != NULL && msg->msg_iovlen != 0),
  870. sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
  871. if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
  872. #if LWIP_TCP
  873. write_flags = NETCONN_COPY |
  874. ((flags & MSG_MORE) ? NETCONN_MORE : 0) |
  875. ((flags & MSG_DONTWAIT) ? NETCONN_DONTBLOCK : 0);
  876. for (i = 0; i < msg->msg_iovlen; i++) {
  877. u8_t apiflags = write_flags;
  878. if (i + 1 < msg->msg_iovlen) {
  879. apiflags |= NETCONN_MORE;
  880. }
  881. written = 0;
  882. err = netconn_write_partly(sock->conn, msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len, write_flags, &written);
  883. if (err == ERR_OK) {
  884. size += written;
  885. /* check that the entire IO vector was accepected, if not return a partial write */
  886. if (written != msg->msg_iov[i].iov_len)
  887. break;
  888. }
  889. /* none of this IO vector was accepted, but previous was, return partial write and conceal ERR_WOULDBLOCK */
  890. else if (err == ERR_WOULDBLOCK && size > 0) {
  891. err = ERR_OK;
  892. /* let ERR_WOULDBLOCK persist on the netconn since we are returning ERR_OK */
  893. break;
  894. } else {
  895. size = -1;
  896. break;
  897. }
  898. }
  899. sock_set_errno(sock, err_to_errno(err));
  900. return size;
  901. #else /* LWIP_TCP */
  902. sock_set_errno(sock, err_to_errno(ERR_ARG));
  903. return -1;
  904. #endif /* LWIP_TCP */
  905. }
  906. /* else, UDP and RAW NETCONNs */
  907. #if LWIP_UDP || LWIP_RAW
  908. {
  909. struct netbuf *chain_buf;
  910. LWIP_UNUSED_ARG(flags);
  911. LWIP_ERROR("lwip_sendmsg: invalid msghdr name", (((msg->msg_name == NULL) && (msg->msg_namelen == 0)) ||
  912. IS_SOCK_ADDR_LEN_VALID(msg->msg_namelen)) ,
  913. sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
  914. /* initialize chain buffer with destination */
  915. chain_buf = netbuf_new();
  916. if (!chain_buf) {
  917. sock_set_errno(sock, err_to_errno(ERR_MEM));
  918. return -1;
  919. }
  920. if (msg->msg_name) {
  921. u16_t remote_port;
  922. SOCKADDR_TO_IPADDR_PORT((const struct sockaddr *)msg->msg_name, &chain_buf->addr, remote_port);
  923. netbuf_fromport(chain_buf) = remote_port;
  924. }
  925. #if LWIP_NETIF_TX_SINGLE_PBUF
  926. for (i = 0; i < msg->msg_iovlen; i++) {
  927. size += msg->msg_iov[i].iov_len;
  928. }
  929. /* Allocate a new netbuf and copy the data into it. */
  930. if (netbuf_alloc(chain_buf, (u16_t)size) == NULL) {
  931. err = ERR_MEM;
  932. } else {
  933. /* flatten the IO vectors */
  934. size_t offset = 0;
  935. for (i = 0; i < msg->msg_iovlen; i++) {
  936. MEMCPY(&((u8_t*)chain_buf->p->payload)[offset], msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len);
  937. offset += msg->msg_iov[i].iov_len;
  938. }
  939. #if LWIP_CHECKSUM_ON_COPY
  940. {
  941. /* This can be improved by using LWIP_CHKSUM_COPY() and aggregating the checksum for each IO vector */
  942. u16_t chksum = ~inet_chksum_pbuf(chain_buf->p);
  943. netbuf_set_chksum(chain_buf, chksum);
  944. }
  945. #endif /* LWIP_CHECKSUM_ON_COPY */
  946. err = ERR_OK;
  947. }
  948. #else /* LWIP_NETIF_TX_SINGLE_PBUF */
  949. /* create a chained netbuf from the IO vectors. NOTE: we assemble a pbuf chain
  950. manually to avoid having to allocate, chain, and delete a netbuf for each iov */
  951. for (i = 0; i < msg->msg_iovlen; i++) {
  952. struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF);
  953. if (p == NULL) {
  954. err = ERR_MEM; /* let netbuf_delete() cleanup chain_buf */
  955. break;
  956. }
  957. p->payload = msg->msg_iov[i].iov_base;
  958. LWIP_ASSERT("iov_len < u16_t", msg->msg_iov[i].iov_len <= 0xFFFF);
  959. p->len = p->tot_len = (u16_t)msg->msg_iov[i].iov_len;
  960. /* netbuf empty, add new pbuf */
  961. if (chain_buf->p == NULL) {
  962. chain_buf->p = chain_buf->ptr = p;
  963. /* add pbuf to existing pbuf chain */
  964. } else {
  965. pbuf_cat(chain_buf->p, p);
  966. }
  967. }
  968. /* save size of total chain */
  969. if (err == ERR_OK) {
  970. size = netbuf_len(chain_buf);
  971. }
  972. #endif /* LWIP_NETIF_TX_SINGLE_PBUF */
  973. if (err == ERR_OK) {
  974. #if LWIP_IPV4 && LWIP_IPV6
  975. /* Dual-stack: Unmap IPv4 mapped IPv6 addresses */
  976. if (IP_IS_V6_VAL(chain_buf->addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(&chain_buf->addr))) {
  977. unmap_ipv4_mapped_ipv6(ip_2_ip4(&chain_buf->addr), ip_2_ip6(&chain_buf->addr));
  978. IP_SET_TYPE_VAL(chain_buf->addr, IPADDR_TYPE_V4);
  979. }
  980. #endif /* LWIP_IPV4 && LWIP_IPV6 */
  981. /* send the data */
  982. err = netconn_send(sock->conn, chain_buf);
  983. }
  984. /* deallocated the buffer */
  985. netbuf_delete(chain_buf);
  986. sock_set_errno(sock, err_to_errno(err));
  987. return (err == ERR_OK ? size : -1);
  988. }
  989. #else /* LWIP_UDP || LWIP_RAW */
  990. sock_set_errno(sock, err_to_errno(ERR_ARG));
  991. return -1;
  992. #endif /* LWIP_UDP || LWIP_RAW */
  993. }
  994. int
  995. lwip_sendto(int s, const void *data, size_t size, int flags,
  996. const struct sockaddr *to, socklen_t tolen)
  997. {
  998. struct lwip_sock *sock;
  999. err_t err;
  1000. u16_t short_size;
  1001. u16_t remote_port;
  1002. struct netbuf buf;
  1003. sock = get_socket(s);
  1004. if (!sock) {
  1005. return -1;
  1006. }
  1007. if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
  1008. #if LWIP_TCP
  1009. return lwip_send(s, data, size, flags);
  1010. #else /* LWIP_TCP */
  1011. LWIP_UNUSED_ARG(flags);
  1012. sock_set_errno(sock, err_to_errno(ERR_ARG));
  1013. return -1;
  1014. #endif /* LWIP_TCP */
  1015. }
  1016. /* @todo: split into multiple sendto's? */
  1017. LWIP_ASSERT("lwip_sendto: size must fit in u16_t", size <= 0xffff);
  1018. short_size = (u16_t)size;
  1019. LWIP_ERROR("lwip_sendto: invalid address", (((to == NULL) && (tolen == 0)) ||
  1020. (IS_SOCK_ADDR_LEN_VALID(tolen) &&
  1021. IS_SOCK_ADDR_TYPE_VALID(to) && IS_SOCK_ADDR_ALIGNED(to))),
  1022. sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
  1023. LWIP_UNUSED_ARG(tolen);
  1024. /* initialize a buffer */
  1025. buf.p = buf.ptr = NULL;
  1026. #if LWIP_CHECKSUM_ON_COPY
  1027. buf.flags = 0;
  1028. #endif /* LWIP_CHECKSUM_ON_COPY */
  1029. if (to) {
  1030. SOCKADDR_TO_IPADDR_PORT(to, &buf.addr, remote_port);
  1031. } else {
  1032. remote_port = 0;
  1033. ip_addr_set_any(NETCONNTYPE_ISIPV6(netconn_type(sock->conn)), &buf.addr);
  1034. }
  1035. netbuf_fromport(&buf) = remote_port;
  1036. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_sendto(%d, data=%p, short_size=%"U16_F", flags=0x%x to=",
  1037. s, data, short_size, flags));
  1038. ip_addr_debug_print(SOCKETS_DEBUG, &buf.addr);
  1039. LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", remote_port));
  1040. /* make the buffer point to the data that should be sent */
  1041. #if LWIP_NETIF_TX_SINGLE_PBUF
  1042. /* Allocate a new netbuf and copy the data into it. */
  1043. if (netbuf_alloc(&buf, short_size) == NULL) {
  1044. err = ERR_MEM;
  1045. } else {
  1046. #if LWIP_CHECKSUM_ON_COPY
  1047. if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_RAW) {
  1048. u16_t chksum = LWIP_CHKSUM_COPY(buf.p->payload, data, short_size);
  1049. netbuf_set_chksum(&buf, chksum);
  1050. } else
  1051. #endif /* LWIP_CHECKSUM_ON_COPY */
  1052. {
  1053. MEMCPY(buf.p->payload, data, short_size);
  1054. }
  1055. err = ERR_OK;
  1056. }
  1057. #else /* LWIP_NETIF_TX_SINGLE_PBUF */
  1058. err = netbuf_ref(&buf, data, short_size);
  1059. #endif /* LWIP_NETIF_TX_SINGLE_PBUF */
  1060. if (err == ERR_OK) {
  1061. #if LWIP_IPV4 && LWIP_IPV6
  1062. /* Dual-stack: Unmap IPv4 mapped IPv6 addresses */
  1063. if (IP_IS_V6_VAL(buf.addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(&buf.addr))) {
  1064. unmap_ipv4_mapped_ipv6(ip_2_ip4(&buf.addr), ip_2_ip6(&buf.addr));
  1065. IP_SET_TYPE_VAL(buf.addr, IPADDR_TYPE_V4);
  1066. }
  1067. #endif /* LWIP_IPV4 && LWIP_IPV6 */
  1068. /* send the data */
  1069. err = netconn_send(sock->conn, &buf);
  1070. }
  1071. /* deallocated the buffer */
  1072. netbuf_free(&buf);
  1073. sock_set_errno(sock, err_to_errno(err));
  1074. return (err == ERR_OK ? short_size : -1);
  1075. }
  1076. int
  1077. lwip_socket(int domain, int type, int protocol)
  1078. {
  1079. struct netconn *conn;
  1080. int i;
  1081. LWIP_UNUSED_ARG(domain); /* @todo: check this */
  1082. /* create a netconn */
  1083. switch (type) {
  1084. case SOCK_RAW:
  1085. conn = netconn_new_with_proto_and_callback(DOMAIN_TO_NETCONN_TYPE(domain, NETCONN_RAW),
  1086. (u8_t)protocol, event_callback);
  1087. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ",
  1088. domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
  1089. break;
  1090. case SOCK_DGRAM:
  1091. conn = netconn_new_with_callback(DOMAIN_TO_NETCONN_TYPE(domain,
  1092. ((protocol == IPPROTO_UDPLITE) ? NETCONN_UDPLITE : NETCONN_UDP)) ,
  1093. event_callback);
  1094. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_DGRAM, %d) = ",
  1095. domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
  1096. break;
  1097. case SOCK_STREAM:
  1098. conn = netconn_new_with_callback(DOMAIN_TO_NETCONN_TYPE(domain, NETCONN_TCP), event_callback);
  1099. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_STREAM, %d) = ",
  1100. domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
  1101. break;
  1102. default:
  1103. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%d, %d/UNKNOWN, %d) = -1\n",
  1104. domain, type, protocol));
  1105. set_errno(EINVAL);
  1106. return -1;
  1107. }
  1108. if (!conn) {
  1109. LWIP_DEBUGF(SOCKETS_DEBUG, ("-1 / ENOBUFS (could not create netconn)\n"));
  1110. set_errno(ENOBUFS);
  1111. return -1;
  1112. }
  1113. i = alloc_socket(conn, 0);
  1114. if (i == -1) {
  1115. netconn_delete(conn);
  1116. set_errno(ENFILE);
  1117. return -1;
  1118. }
  1119. conn->socket = i;
  1120. LWIP_DEBUGF(SOCKETS_DEBUG, ("%d\n", i));
  1121. set_errno(0);
  1122. return i;
  1123. }
  1124. int
  1125. lwip_write(int s, const void *data, size_t size)
  1126. {
  1127. return lwip_send(s, data, size, 0);
  1128. }
  1129. int
  1130. lwip_writev(int s, const struct iovec *iov, int iovcnt)
  1131. {
  1132. struct msghdr msg;
  1133. msg.msg_name = NULL;
  1134. msg.msg_namelen = 0;
  1135. /* Hack: we have to cast via number to cast from 'const' pointer to non-const.
  1136. Blame the opengroup standard for this inconsistency. */
  1137. msg.msg_iov = LWIP_CONST_CAST(struct iovec *, iov);
  1138. msg.msg_iovlen = iovcnt;
  1139. msg.msg_control = NULL;
  1140. msg.msg_controllen = 0;
  1141. msg.msg_flags = 0;
  1142. return lwip_sendmsg(s, &msg, 0);
  1143. }
  1144. /**
  1145. * Go through the readset and writeset lists and see which socket of the sockets
  1146. * set in the sets has events. On return, readset, writeset and exceptset have
  1147. * the sockets enabled that had events.
  1148. *
  1149. * @param maxfdp1 the highest socket index in the sets
  1150. * @param readset_in set of sockets to check for read events
  1151. * @param writeset_in set of sockets to check for write events
  1152. * @param exceptset_in set of sockets to check for error events
  1153. * @param readset_out set of sockets that had read events
  1154. * @param writeset_out set of sockets that had write events
  1155. * @param exceptset_out set os sockets that had error events
  1156. * @return number of sockets that had events (read/write/exception) (>= 0)
  1157. */
  1158. static int
  1159. lwip_selscan(int maxfdp1, fd_set *readset_in, fd_set *writeset_in, fd_set *exceptset_in,
  1160. fd_set *readset_out, fd_set *writeset_out, fd_set *exceptset_out)
  1161. {
  1162. int i, nready = 0;
  1163. fd_set lreadset, lwriteset, lexceptset;
  1164. struct lwip_sock *sock;
  1165. SYS_ARCH_DECL_PROTECT(lev);
  1166. FD_ZERO(&lreadset);
  1167. FD_ZERO(&lwriteset);
  1168. FD_ZERO(&lexceptset);
  1169. /* Go through each socket in each list to count number of sockets which
  1170. currently match */
  1171. for (i = LWIP_SOCKET_OFFSET; i < maxfdp1; i++) {
  1172. /* if this FD is not in the set, continue */
  1173. if (!(readset_in && FD_ISSET(i, readset_in)) &&
  1174. !(writeset_in && FD_ISSET(i, writeset_in)) &&
  1175. !(exceptset_in && FD_ISSET(i, exceptset_in))) {
  1176. continue;
  1177. }
  1178. /* First get the socket's status (protected)... */
  1179. SYS_ARCH_PROTECT(lev);
  1180. sock = tryget_socket(i);
  1181. if (sock != NULL) {
  1182. void* lastdata = sock->lastdata;
  1183. s16_t rcvevent = sock->rcvevent;
  1184. u16_t sendevent = sock->sendevent;
  1185. u16_t errevent = sock->errevent;
  1186. SYS_ARCH_UNPROTECT(lev);
  1187. /* ... then examine it: */
  1188. /* See if netconn of this socket is ready for read */
  1189. if (readset_in && FD_ISSET(i, readset_in) && ((lastdata != NULL) || (rcvevent > 0))) {
  1190. FD_SET(i, &lreadset);
  1191. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for reading\n", i));
  1192. nready++;
  1193. }
  1194. /* See if netconn of this socket is ready for write */
  1195. if (writeset_in && FD_ISSET(i, writeset_in) && (sendevent != 0)) {
  1196. FD_SET(i, &lwriteset);
  1197. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for writing\n", i));
  1198. nready++;
  1199. }
  1200. /* See if netconn of this socket had an error */
  1201. if (exceptset_in && FD_ISSET(i, exceptset_in) && (errevent != 0)) {
  1202. FD_SET(i, &lexceptset);
  1203. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for exception\n", i));
  1204. nready++;
  1205. }
  1206. } else {
  1207. SYS_ARCH_UNPROTECT(lev);
  1208. /* continue on to next FD in list */
  1209. }
  1210. }
  1211. /* copy local sets to the ones provided as arguments */
  1212. *readset_out = lreadset;
  1213. *writeset_out = lwriteset;
  1214. *exceptset_out = lexceptset;
  1215. LWIP_ASSERT("nready >= 0", nready >= 0);
  1216. return nready;
  1217. }
  1218. int
  1219. lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
  1220. struct timeval *timeout)
  1221. {
  1222. u32_t waitres = 0;
  1223. int nready;
  1224. fd_set lreadset, lwriteset, lexceptset;
  1225. u32_t msectimeout;
  1226. struct lwip_select_cb select_cb;
  1227. int i;
  1228. int maxfdp2;
  1229. #if LWIP_NETCONN_SEM_PER_THREAD
  1230. int waited = 0;
  1231. #endif
  1232. SYS_ARCH_DECL_PROTECT(lev);
  1233. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select(%d, %p, %p, %p, tvsec=%"S32_F" tvusec=%"S32_F")\n",
  1234. maxfdp1, (void *)readset, (void *) writeset, (void *) exceptset,
  1235. timeout ? (s32_t)timeout->tv_sec : (s32_t)-1,
  1236. timeout ? (s32_t)timeout->tv_usec : (s32_t)-1));
  1237. /* Go through each socket in each list to count number of sockets which
  1238. currently match */
  1239. nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset);
  1240. /* If we don't have any current events, then suspend if we are supposed to */
  1241. if (!nready) {
  1242. if (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0) {
  1243. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: no timeout, returning 0\n"));
  1244. /* This is OK as the local fdsets are empty and nready is zero,
  1245. or we would have returned earlier. */
  1246. goto return_copy_fdsets;
  1247. }
  1248. /* None ready: add our semaphore to list:
  1249. We don't actually need any dynamic memory. Our entry on the
  1250. list is only valid while we are in this function, so it's ok
  1251. to use local variables. */
  1252. select_cb.next = NULL;
  1253. select_cb.prev = NULL;
  1254. select_cb.readset = readset;
  1255. select_cb.writeset = writeset;
  1256. select_cb.exceptset = exceptset;
  1257. select_cb.sem_signalled = 0;
  1258. #if LWIP_NETCONN_SEM_PER_THREAD
  1259. select_cb.sem = LWIP_NETCONN_THREAD_SEM_GET();
  1260. #else /* LWIP_NETCONN_SEM_PER_THREAD */
  1261. if (sys_sem_new(&select_cb.sem, 0) != ERR_OK) {
  1262. /* failed to create semaphore */
  1263. set_errno(ENOMEM);
  1264. return -1;
  1265. }
  1266. #endif /* LWIP_NETCONN_SEM_PER_THREAD */
  1267. /* Protect the select_cb_list */
  1268. SYS_ARCH_PROTECT(lev);
  1269. /* Put this select_cb on top of list */
  1270. select_cb.next = select_cb_list;
  1271. if (select_cb_list != NULL) {
  1272. select_cb_list->prev = &select_cb;
  1273. }
  1274. select_cb_list = &select_cb;
  1275. /* Increasing this counter tells event_callback that the list has changed. */
  1276. select_cb_ctr++;
  1277. /* Now we can safely unprotect */
  1278. SYS_ARCH_UNPROTECT(lev);
  1279. /* Increase select_waiting for each socket we are interested in */
  1280. maxfdp2 = maxfdp1;
  1281. for (i = LWIP_SOCKET_OFFSET; i < maxfdp1; i++) {
  1282. if ((readset && FD_ISSET(i, readset)) ||
  1283. (writeset && FD_ISSET(i, writeset)) ||
  1284. (exceptset && FD_ISSET(i, exceptset))) {
  1285. struct lwip_sock *sock;
  1286. SYS_ARCH_PROTECT(lev);
  1287. sock = tryget_socket(i);
  1288. if (sock != NULL) {
  1289. sock->select_waiting++;
  1290. LWIP_ASSERT("sock->select_waiting > 0", sock->select_waiting > 0);
  1291. } else {
  1292. /* Not a valid socket */
  1293. nready = -1;
  1294. maxfdp2 = i;
  1295. SYS_ARCH_UNPROTECT(lev);
  1296. break;
  1297. }
  1298. SYS_ARCH_UNPROTECT(lev);
  1299. }
  1300. }
  1301. if (nready >= 0) {
  1302. /* Call lwip_selscan again: there could have been events between
  1303. the last scan (without us on the list) and putting us on the list! */
  1304. nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset);
  1305. if (!nready) {
  1306. /* Still none ready, just wait to be woken */
  1307. if (timeout == 0) {
  1308. /* Wait forever */
  1309. msectimeout = 0;
  1310. } else {
  1311. msectimeout = ((timeout->tv_sec * 1000) + ((timeout->tv_usec + 500)/1000));
  1312. if (msectimeout == 0) {
  1313. /* Wait 1ms at least (0 means wait forever) */
  1314. msectimeout = 1;
  1315. }
  1316. }
  1317. waitres = sys_arch_sem_wait(SELECT_SEM_PTR(select_cb.sem), msectimeout);
  1318. #if LWIP_NETCONN_SEM_PER_THREAD
  1319. waited = 1;
  1320. #endif
  1321. }
  1322. }
  1323. /* Decrease select_waiting for each socket we are interested in */
  1324. for (i = LWIP_SOCKET_OFFSET; i < maxfdp2; i++) {
  1325. if ((readset && FD_ISSET(i, readset)) ||
  1326. (writeset && FD_ISSET(i, writeset)) ||
  1327. (exceptset && FD_ISSET(i, exceptset))) {
  1328. struct lwip_sock *sock;
  1329. SYS_ARCH_PROTECT(lev);
  1330. sock = tryget_socket(i);
  1331. if (sock != NULL) {
  1332. /* for now, handle select_waiting==0... */
  1333. LWIP_ASSERT("sock->select_waiting > 0", sock->select_waiting > 0);
  1334. if (sock->select_waiting > 0) {
  1335. sock->select_waiting--;
  1336. }
  1337. } else {
  1338. /* Not a valid socket */
  1339. nready = -1;
  1340. }
  1341. SYS_ARCH_UNPROTECT(lev);
  1342. }
  1343. }
  1344. /* Take us off the list */
  1345. SYS_ARCH_PROTECT(lev);
  1346. if (select_cb.next != NULL) {
  1347. select_cb.next->prev = select_cb.prev;
  1348. }
  1349. if (select_cb_list == &select_cb) {
  1350. LWIP_ASSERT("select_cb.prev == NULL", select_cb.prev == NULL);
  1351. select_cb_list = select_cb.next;
  1352. } else {
  1353. LWIP_ASSERT("select_cb.prev != NULL", select_cb.prev != NULL);
  1354. select_cb.prev->next = select_cb.next;
  1355. }
  1356. /* Increasing this counter tells event_callback that the list has changed. */
  1357. select_cb_ctr++;
  1358. SYS_ARCH_UNPROTECT(lev);
  1359. #if LWIP_NETCONN_SEM_PER_THREAD
  1360. if (select_cb.sem_signalled && (!waited || (waitres == SYS_ARCH_TIMEOUT))) {
  1361. /* don't leave the thread-local semaphore signalled */
  1362. sys_arch_sem_wait(select_cb.sem, 1);
  1363. }
  1364. #else /* LWIP_NETCONN_SEM_PER_THREAD */
  1365. sys_sem_free(&select_cb.sem);
  1366. #endif /* LWIP_NETCONN_SEM_PER_THREAD */
  1367. if (nready < 0) {
  1368. /* This happens when a socket got closed while waiting */
  1369. set_errno(EBADF);
  1370. return -1;
  1371. }
  1372. if (waitres == SYS_ARCH_TIMEOUT) {
  1373. /* Timeout */
  1374. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: timeout expired\n"));
  1375. /* This is OK as the local fdsets are empty and nready is zero,
  1376. or we would have returned earlier. */
  1377. goto return_copy_fdsets;
  1378. }
  1379. /* See what's set */
  1380. nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset);
  1381. }
  1382. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: nready=%d\n", nready));
  1383. return_copy_fdsets:
  1384. set_errno(0);
  1385. if (readset) {
  1386. *readset = lreadset;
  1387. }
  1388. if (writeset) {
  1389. *writeset = lwriteset;
  1390. }
  1391. if (exceptset) {
  1392. *exceptset = lexceptset;
  1393. }
  1394. return nready;
  1395. }
  1396. /**
  1397. * Callback registered in the netconn layer for each socket-netconn.
  1398. * Processes recvevent (data available) and wakes up tasks waiting for select.
  1399. */
  1400. static void
  1401. event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)
  1402. {
  1403. int s;
  1404. struct lwip_sock *sock;
  1405. struct lwip_select_cb *scb;
  1406. int last_select_cb_ctr;
  1407. SYS_ARCH_DECL_PROTECT(lev);
  1408. LWIP_UNUSED_ARG(len);
  1409. /* Get socket */
  1410. if (conn) {
  1411. s = conn->socket;
  1412. if (s < 0) {
  1413. /* Data comes in right away after an accept, even though
  1414. * the server task might not have created a new socket yet.
  1415. * Just count down (or up) if that's the case and we
  1416. * will use the data later. Note that only receive events
  1417. * can happen before the new socket is set up. */
  1418. SYS_ARCH_PROTECT(lev);
  1419. if (conn->socket < 0) {
  1420. if (evt == NETCONN_EVT_RCVPLUS) {
  1421. conn->socket--;
  1422. }
  1423. SYS_ARCH_UNPROTECT(lev);
  1424. return;
  1425. }
  1426. s = conn->socket;
  1427. SYS_ARCH_UNPROTECT(lev);
  1428. }
  1429. sock = get_socket(s);
  1430. if (!sock) {
  1431. return;
  1432. }
  1433. } else {
  1434. return;
  1435. }
  1436. SYS_ARCH_PROTECT(lev);
  1437. /* Set event as required */
  1438. switch (evt) {
  1439. case NETCONN_EVT_RCVPLUS:
  1440. sock->rcvevent++;
  1441. break;
  1442. case NETCONN_EVT_RCVMINUS:
  1443. sock->rcvevent--;
  1444. break;
  1445. case NETCONN_EVT_SENDPLUS:
  1446. sock->sendevent = 1;
  1447. break;
  1448. case NETCONN_EVT_SENDMINUS:
  1449. sock->sendevent = 0;
  1450. break;
  1451. case NETCONN_EVT_ERROR:
  1452. sock->errevent = 1;
  1453. break;
  1454. default:
  1455. LWIP_ASSERT("unknown event", 0);
  1456. break;
  1457. }
  1458. if (sock->select_waiting == 0) {
  1459. /* noone is waiting for this socket, no need to check select_cb_list */
  1460. SYS_ARCH_UNPROTECT(lev);
  1461. return;
  1462. }
  1463. /* Now decide if anyone is waiting for this socket */
  1464. /* NOTE: This code goes through the select_cb_list list multiple times
  1465. ONLY IF a select was actually waiting. We go through the list the number
  1466. of waiting select calls + 1. This list is expected to be small. */
  1467. /* At this point, SYS_ARCH is still protected! */
  1468. again:
  1469. for (scb = select_cb_list; scb != NULL; scb = scb->next) {
  1470. /* remember the state of select_cb_list to detect changes */
  1471. last_select_cb_ctr = select_cb_ctr;
  1472. if (scb->sem_signalled == 0) {
  1473. /* semaphore not signalled yet */
  1474. int do_signal = 0;
  1475. /* Test this select call for our socket */
  1476. if (sock->rcvevent > 0) {
  1477. if (scb->readset && FD_ISSET(s, scb->readset)) {
  1478. do_signal = 1;
  1479. }
  1480. }
  1481. if (sock->sendevent != 0) {
  1482. if (!do_signal && scb->writeset && FD_ISSET(s, scb->writeset)) {
  1483. do_signal = 1;
  1484. }
  1485. }
  1486. if (sock->errevent != 0) {
  1487. if (!do_signal && scb->exceptset && FD_ISSET(s, scb->exceptset)) {
  1488. do_signal = 1;
  1489. }
  1490. }
  1491. if (do_signal) {
  1492. scb->sem_signalled = 1;
  1493. /* Don't call SYS_ARCH_UNPROTECT() before signaling the semaphore, as this might
  1494. lead to the select thread taking itself off the list, invalidating the semaphore. */
  1495. sys_sem_signal(SELECT_SEM_PTR(scb->sem));
  1496. }
  1497. }
  1498. /* unlock interrupts with each step */
  1499. SYS_ARCH_UNPROTECT(lev);
  1500. /* this makes sure interrupt protection time is short */
  1501. SYS_ARCH_PROTECT(lev);
  1502. if (last_select_cb_ctr != select_cb_ctr) {
  1503. /* someone has changed select_cb_list, restart at the beginning */
  1504. goto again;
  1505. }
  1506. }
  1507. SYS_ARCH_UNPROTECT(lev);
  1508. }
  1509. /**
  1510. * Close one end of a full-duplex connection.
  1511. */
  1512. int
  1513. lwip_shutdown(int s, int how)
  1514. {
  1515. struct lwip_sock *sock;
  1516. err_t err;
  1517. u8_t shut_rx = 0, shut_tx = 0;
  1518. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_shutdown(%d, how=%d)\n", s, how));
  1519. sock = get_socket(s);
  1520. if (!sock) {
  1521. return -1;
  1522. }
  1523. if (sock->conn != NULL) {
  1524. if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) {
  1525. sock_set_errno(sock, EOPNOTSUPP);
  1526. return -1;
  1527. }
  1528. } else {
  1529. sock_set_errno(sock, ENOTCONN);
  1530. return -1;
  1531. }
  1532. if (how == SHUT_RD) {
  1533. shut_rx = 1;
  1534. } else if (how == SHUT_WR) {
  1535. shut_tx = 1;
  1536. } else if (how == SHUT_RDWR) {
  1537. shut_rx = 1;
  1538. shut_tx = 1;
  1539. } else {
  1540. sock_set_errno(sock, EINVAL);
  1541. return -1;
  1542. }
  1543. err = netconn_shutdown(sock->conn, shut_rx, shut_tx);
  1544. sock_set_errno(sock, err_to_errno(err));
  1545. return (err == ERR_OK ? 0 : -1);
  1546. }
  1547. static int
  1548. lwip_getaddrname(int s, struct sockaddr *name, socklen_t *namelen, u8_t local)
  1549. {
  1550. struct lwip_sock *sock;
  1551. union sockaddr_aligned saddr;
  1552. ip_addr_t naddr;
  1553. u16_t port;
  1554. err_t err;
  1555. sock = get_socket(s);
  1556. if (!sock) {
  1557. return -1;
  1558. }
  1559. /* get the IP address and port */
  1560. err = netconn_getaddr(sock->conn, &naddr, &port, local);
  1561. if (err != ERR_OK) {
  1562. sock_set_errno(sock, err_to_errno(err));
  1563. return -1;
  1564. }
  1565. #if LWIP_IPV4 && LWIP_IPV6
  1566. /* Dual-stack: Map IPv4 addresses to IPv4 mapped IPv6 */
  1567. if (NETCONNTYPE_ISIPV6(netconn_type(sock->conn)) &&
  1568. IP_IS_V4_VAL(naddr)) {
  1569. ip4_2_ipv4_mapped_ipv6(ip_2_ip6(&naddr), ip_2_ip4(&naddr));
  1570. IP_SET_TYPE_VAL(naddr, IPADDR_TYPE_V6);
  1571. }
  1572. #endif /* LWIP_IPV4 && LWIP_IPV6 */
  1573. IPADDR_PORT_TO_SOCKADDR(&saddr, &naddr, port);
  1574. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getaddrname(%d, addr=", s));
  1575. ip_addr_debug_print_val(SOCKETS_DEBUG, naddr);
  1576. LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", port));
  1577. if (*namelen > saddr.sa.sa_len) {
  1578. *namelen = saddr.sa.sa_len;
  1579. }
  1580. MEMCPY(name, &saddr, *namelen);
  1581. sock_set_errno(sock, 0);
  1582. return 0;
  1583. }
  1584. int
  1585. lwip_getpeername(int s, struct sockaddr *name, socklen_t *namelen)
  1586. {
  1587. return lwip_getaddrname(s, name, namelen, 0);
  1588. }
  1589. int
  1590. lwip_getsockname(int s, struct sockaddr *name, socklen_t *namelen)
  1591. {
  1592. return lwip_getaddrname(s, name, namelen, 1);
  1593. }
  1594. int
  1595. lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
  1596. {
  1597. u8_t err;
  1598. struct lwip_sock *sock = get_socket(s);
  1599. #if !LWIP_TCPIP_CORE_LOCKING
  1600. LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(data);
  1601. #endif /* !LWIP_TCPIP_CORE_LOCKING */
  1602. if (!sock) {
  1603. return -1;
  1604. }
  1605. if ((NULL == optval) || (NULL == optlen)) {
  1606. sock_set_errno(sock, EFAULT);
  1607. return -1;
  1608. }
  1609. #if LWIP_TCPIP_CORE_LOCKING
  1610. /* core-locking can just call the -impl function */
  1611. LOCK_TCPIP_CORE();
  1612. err = lwip_getsockopt_impl(s, level, optname, optval, optlen);
  1613. UNLOCK_TCPIP_CORE();
  1614. #else /* LWIP_TCPIP_CORE_LOCKING */
  1615. #if LWIP_MPU_COMPATIBLE
  1616. /* MPU_COMPATIBLE copies the optval data, so check for max size here */
  1617. if (*optlen > LWIP_SETGETSOCKOPT_MAXOPTLEN) {
  1618. sock_set_errno(sock, ENOBUFS);
  1619. return -1;
  1620. }
  1621. #endif /* LWIP_MPU_COMPATIBLE */
  1622. LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(data, sock);
  1623. LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).s = s;
  1624. LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).level = level;
  1625. LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optname = optname;
  1626. LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen = *optlen;
  1627. #if !LWIP_MPU_COMPATIBLE
  1628. LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval.p = optval;
  1629. #endif /* !LWIP_MPU_COMPATIBLE */
  1630. LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err = 0;
  1631. #if LWIP_NETCONN_SEM_PER_THREAD
  1632. LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = LWIP_NETCONN_THREAD_SEM_GET();
  1633. #else
  1634. LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = &sock->conn->op_completed;
  1635. #endif
  1636. err = tcpip_callback(lwip_getsockopt_callback, &LWIP_SETGETSOCKOPT_DATA_VAR_REF(data));
  1637. if (err != ERR_OK) {
  1638. LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data);
  1639. sock_set_errno(sock, err_to_errno(err));
  1640. return -1;
  1641. }
  1642. sys_arch_sem_wait((sys_sem_t*)(LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem), 0);
  1643. /* write back optlen and optval */
  1644. *optlen = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen;
  1645. #if LWIP_MPU_COMPATIBLE
  1646. MEMCPY(optval, LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval,
  1647. LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen);
  1648. #endif /* LWIP_MPU_COMPATIBLE */
  1649. /* maybe lwip_getsockopt_internal has changed err */
  1650. err = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err;
  1651. LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data);
  1652. #endif /* LWIP_TCPIP_CORE_LOCKING */
  1653. sock_set_errno(sock, err);
  1654. return err ? -1 : 0;
  1655. }
  1656. #if !LWIP_TCPIP_CORE_LOCKING
  1657. /** lwip_getsockopt_callback: only used without CORE_LOCKING
  1658. * to get into the tcpip_thread
  1659. */
  1660. static void
  1661. lwip_getsockopt_callback(void *arg)
  1662. {
  1663. struct lwip_setgetsockopt_data *data;
  1664. LWIP_ASSERT("arg != NULL", arg != NULL);
  1665. data = (struct lwip_setgetsockopt_data*)arg;
  1666. data->err = lwip_getsockopt_impl(data->s, data->level, data->optname,
  1667. #if LWIP_MPU_COMPATIBLE
  1668. data->optval,
  1669. #else /* LWIP_MPU_COMPATIBLE */
  1670. data->optval.p,
  1671. #endif /* LWIP_MPU_COMPATIBLE */
  1672. &data->optlen);
  1673. sys_sem_signal((sys_sem_t*)(data->completed_sem));
  1674. }
  1675. #endif /* LWIP_TCPIP_CORE_LOCKING */
  1676. /** lwip_getsockopt_impl: the actual implementation of getsockopt:
  1677. * same argument as lwip_getsockopt, either called directly or through callback
  1678. */
  1679. static u8_t
  1680. lwip_getsockopt_impl(int s, int level, int optname, void *optval, socklen_t *optlen)
  1681. {
  1682. u8_t err = 0;
  1683. struct lwip_sock *sock = tryget_socket(s);
  1684. if (!sock) {
  1685. return EBADF;
  1686. }
  1687. switch (level) {
  1688. /* Level: SOL_SOCKET */
  1689. case SOL_SOCKET:
  1690. switch (optname) {
  1691. #if LWIP_TCP
  1692. case SO_ACCEPTCONN:
  1693. LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int);
  1694. if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_TCP) {
  1695. return ENOPROTOOPT;
  1696. }
  1697. if ((sock->conn->pcb.tcp != NULL) && (sock->conn->pcb.tcp->state == LISTEN)) {
  1698. *(int*)optval = 1;
  1699. } else {
  1700. *(int*)optval = 0;
  1701. }
  1702. break;
  1703. #endif /* LWIP_TCP */
  1704. /* The option flags */
  1705. case SO_BROADCAST:
  1706. case SO_KEEPALIVE:
  1707. #if SO_REUSE
  1708. case SO_REUSEADDR:
  1709. #endif /* SO_REUSE */
  1710. LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int);
  1711. *(int*)optval = ip_get_option(sock->conn->pcb.ip, optname);
  1712. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, optname=0x%x, ..) = %s\n",
  1713. s, optname, (*(int*)optval?"on":"off")));
  1714. break;
  1715. case SO_TYPE:
  1716. LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, int);
  1717. switch (NETCONNTYPE_GROUP(netconn_type(sock->conn))) {
  1718. case NETCONN_RAW:
  1719. *(int*)optval = SOCK_RAW;
  1720. break;
  1721. case NETCONN_TCP:
  1722. *(int*)optval = SOCK_STREAM;
  1723. break;
  1724. case NETCONN_UDP:
  1725. *(int*)optval = SOCK_DGRAM;
  1726. break;
  1727. default: /* unrecognized socket type */
  1728. *(int*)optval = netconn_type(sock->conn);
  1729. LWIP_DEBUGF(SOCKETS_DEBUG,
  1730. ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE): unrecognized socket type %d\n",
  1731. s, *(int *)optval));
  1732. } /* switch (netconn_type(sock->conn)) */
  1733. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE) = %d\n",
  1734. s, *(int *)optval));
  1735. break;
  1736. case SO_ERROR:
  1737. LWIP_SOCKOPT_CHECK_OPTLEN(*optlen, int);
  1738. /* only overwrite ERR_OK or temporary errors */
  1739. if (((sock->err == 0) || (sock->err == EINPROGRESS)) && (sock->conn != NULL)) {
  1740. sock_set_errno(sock, err_to_errno(sock->conn->last_err));
  1741. }
  1742. *(int *)optval = (sock->err == 0xFF ? (int)-1 : (int)sock->err);
  1743. sock->err = 0;
  1744. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n",
  1745. s, *(int *)optval));
  1746. break;
  1747. #if LWIP_SO_SNDTIMEO
  1748. case SO_SNDTIMEO:
  1749. LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE);
  1750. LWIP_SO_SNDRCVTIMEO_SET(optval, netconn_get_sendtimeout(sock->conn));
  1751. break;
  1752. #endif /* LWIP_SO_SNDTIMEO */
  1753. #if LWIP_SO_RCVTIMEO
  1754. case SO_RCVTIMEO:
  1755. LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE);
  1756. LWIP_SO_SNDRCVTIMEO_SET(optval, netconn_get_recvtimeout(sock->conn));
  1757. break;
  1758. #endif /* LWIP_SO_RCVTIMEO */
  1759. #if LWIP_SO_RCVBUF
  1760. case SO_RCVBUF:
  1761. LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, int);
  1762. *(int *)optval = netconn_get_recvbufsize(sock->conn);
  1763. break;
  1764. #endif /* LWIP_SO_RCVBUF */
  1765. #if LWIP_SO_LINGER
  1766. case SO_LINGER:
  1767. {
  1768. s16_t conn_linger;
  1769. struct linger* linger = (struct linger*)optval;
  1770. LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, struct linger);
  1771. conn_linger = sock->conn->linger;
  1772. if (conn_linger >= 0) {
  1773. linger->l_onoff = 1;
  1774. linger->l_linger = (int)conn_linger;
  1775. } else {
  1776. linger->l_onoff = 0;
  1777. linger->l_linger = 0;
  1778. }
  1779. }
  1780. break;
  1781. #endif /* LWIP_SO_LINGER */
  1782. #if LWIP_UDP
  1783. case SO_NO_CHECK:
  1784. LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, *optlen, int, NETCONN_UDP);
  1785. #if LWIP_UDPLITE
  1786. if ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0) {
  1787. /* this flag is only available for UDP, not for UDP lite */
  1788. return EAFNOSUPPORT;
  1789. }
  1790. #endif /* LWIP_UDPLITE */
  1791. *(int*)optval = (udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_NOCHKSUM) ? 1 : 0;
  1792. break;
  1793. #endif /* LWIP_UDP*/
  1794. default:
  1795. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n",
  1796. s, optname));
  1797. err = ENOPROTOOPT;
  1798. break;
  1799. } /* switch (optname) */
  1800. break;
  1801. /* Level: IPPROTO_IP */
  1802. case IPPROTO_IP:
  1803. switch (optname) {
  1804. case IP_TTL:
  1805. LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int);
  1806. *(int*)optval = sock->conn->pcb.ip->ttl;
  1807. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TTL) = %d\n",
  1808. s, *(int *)optval));
  1809. break;
  1810. case IP_TOS:
  1811. LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int);
  1812. *(int*)optval = sock->conn->pcb.ip->tos;
  1813. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TOS) = %d\n",
  1814. s, *(int *)optval));
  1815. break;
  1816. #if LWIP_MULTICAST_TX_OPTIONS
  1817. case IP_MULTICAST_TTL:
  1818. LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, u8_t);
  1819. if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) {
  1820. return ENOPROTOOPT;
  1821. }
  1822. *(u8_t*)optval = udp_get_multicast_ttl(sock->conn->pcb.udp);
  1823. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_TTL) = %d\n",
  1824. s, *(int *)optval));
  1825. break;
  1826. case IP_MULTICAST_IF:
  1827. LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, struct in_addr);
  1828. if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) {
  1829. return ENOPROTOOPT;
  1830. }
  1831. inet_addr_from_ip4addr((struct in_addr*)optval, udp_get_multicast_netif_addr(sock->conn->pcb.udp));
  1832. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_IF) = 0x%"X32_F"\n",
  1833. s, *(u32_t *)optval));
  1834. break;
  1835. case IP_MULTICAST_LOOP:
  1836. LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, u8_t);
  1837. if ((sock->conn->pcb.udp->flags & UDP_FLAGS_MULTICAST_LOOP) != 0) {
  1838. *(u8_t*)optval = 1;
  1839. } else {
  1840. *(u8_t*)optval = 0;
  1841. }
  1842. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_LOOP) = %d\n",
  1843. s, *(int *)optval));
  1844. break;
  1845. #endif /* LWIP_MULTICAST_TX_OPTIONS */
  1846. default:
  1847. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n",
  1848. s, optname));
  1849. err = ENOPROTOOPT;
  1850. break;
  1851. } /* switch (optname) */
  1852. break;
  1853. #if LWIP_TCP
  1854. /* Level: IPPROTO_TCP */
  1855. case IPPROTO_TCP:
  1856. /* Special case: all IPPROTO_TCP option take an int */
  1857. LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, *optlen, int, NETCONN_TCP);
  1858. if (sock->conn->pcb.tcp->state == LISTEN) {
  1859. return EINVAL;
  1860. }
  1861. switch (optname) {
  1862. case TCP_NODELAY:
  1863. *(int*)optval = tcp_nagle_disabled(sock->conn->pcb.tcp);
  1864. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_NODELAY) = %s\n",
  1865. s, (*(int*)optval)?"on":"off") );
  1866. break;
  1867. case TCP_KEEPALIVE:
  1868. *(int*)optval = (int)sock->conn->pcb.tcp->keep_idle;
  1869. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) = %d\n",
  1870. s, *(int *)optval));
  1871. break;
  1872. #if LWIP_TCP_KEEPALIVE
  1873. case TCP_KEEPIDLE:
  1874. *(int*)optval = (int)(sock->conn->pcb.tcp->keep_idle/1000);
  1875. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_KEEPIDLE) = %d\n",
  1876. s, *(int *)optval));
  1877. break;
  1878. case TCP_KEEPINTVL:
  1879. *(int*)optval = (int)(sock->conn->pcb.tcp->keep_intvl/1000);
  1880. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_KEEPINTVL) = %d\n",
  1881. s, *(int *)optval));
  1882. break;
  1883. case TCP_KEEPCNT:
  1884. *(int*)optval = (int)sock->conn->pcb.tcp->keep_cnt;
  1885. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_KEEPCNT) = %d\n",
  1886. s, *(int *)optval));
  1887. break;
  1888. #endif /* LWIP_TCP_KEEPALIVE */
  1889. default:
  1890. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n",
  1891. s, optname));
  1892. err = ENOPROTOOPT;
  1893. break;
  1894. } /* switch (optname) */
  1895. break;
  1896. #endif /* LWIP_TCP */
  1897. #if LWIP_IPV6
  1898. /* Level: IPPROTO_IPV6 */
  1899. case IPPROTO_IPV6:
  1900. switch (optname) {
  1901. case IPV6_V6ONLY:
  1902. LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, int);
  1903. *(int*)optval = (netconn_get_ipv6only(sock->conn) ? 1 : 0);
  1904. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IPV6, IPV6_V6ONLY) = %d\n",
  1905. s, *(int *)optval));
  1906. break;
  1907. default:
  1908. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IPV6, UNIMPL: optname=0x%x, ..)\n",
  1909. s, optname));
  1910. err = ENOPROTOOPT;
  1911. break;
  1912. } /* switch (optname) */
  1913. break;
  1914. #endif /* LWIP_IPV6 */
  1915. #if LWIP_UDP && LWIP_UDPLITE
  1916. /* Level: IPPROTO_UDPLITE */
  1917. case IPPROTO_UDPLITE:
  1918. /* Special case: all IPPROTO_UDPLITE option take an int */
  1919. LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int);
  1920. /* If this is no UDP lite socket, ignore any options. */
  1921. if (!NETCONNTYPE_ISUDPLITE(netconn_type(sock->conn))) {
  1922. return ENOPROTOOPT;
  1923. }
  1924. switch (optname) {
  1925. case UDPLITE_SEND_CSCOV:
  1926. *(int*)optval = sock->conn->pcb.udp->chksum_len_tx;
  1927. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) = %d\n",
  1928. s, (*(int*)optval)) );
  1929. break;
  1930. case UDPLITE_RECV_CSCOV:
  1931. *(int*)optval = sock->conn->pcb.udp->chksum_len_rx;
  1932. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) = %d\n",
  1933. s, (*(int*)optval)) );
  1934. break;
  1935. default:
  1936. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n",
  1937. s, optname));
  1938. err = ENOPROTOOPT;
  1939. break;
  1940. } /* switch (optname) */
  1941. break;
  1942. #endif /* LWIP_UDP */
  1943. /* Level: IPPROTO_RAW */
  1944. case IPPROTO_RAW:
  1945. switch (optname) {
  1946. #if LWIP_IPV6 && LWIP_RAW
  1947. case IPV6_CHECKSUM:
  1948. LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, *optlen, int, NETCONN_RAW);
  1949. if (sock->conn->pcb.raw->chksum_reqd == 0) {
  1950. *(int *)optval = -1;
  1951. } else {
  1952. *(int *)optval = sock->conn->pcb.raw->chksum_offset;
  1953. }
  1954. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_RAW, IPV6_CHECKSUM) = %d\n",
  1955. s, (*(int*)optval)) );
  1956. break;
  1957. #endif /* LWIP_IPV6 && LWIP_RAW */
  1958. default:
  1959. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_RAW, UNIMPL: optname=0x%x, ..)\n",
  1960. s, optname));
  1961. err = ENOPROTOOPT;
  1962. break;
  1963. } /* switch (optname) */
  1964. break;
  1965. default:
  1966. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n",
  1967. s, level, optname));
  1968. err = ENOPROTOOPT;
  1969. break;
  1970. } /* switch (level) */
  1971. return err;
  1972. }
  1973. int
  1974. lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
  1975. {
  1976. u8_t err = 0;
  1977. struct lwip_sock *sock = get_socket(s);
  1978. #if !LWIP_TCPIP_CORE_LOCKING
  1979. LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(data);
  1980. #endif /* !LWIP_TCPIP_CORE_LOCKING */
  1981. if (!sock) {
  1982. return -1;
  1983. }
  1984. if (NULL == optval) {
  1985. sock_set_errno(sock, EFAULT);
  1986. return -1;
  1987. }
  1988. #if LWIP_TCPIP_CORE_LOCKING
  1989. /* core-locking can just call the -impl function */
  1990. LOCK_TCPIP_CORE();
  1991. err = lwip_setsockopt_impl(s, level, optname, optval, optlen);
  1992. UNLOCK_TCPIP_CORE();
  1993. #else /* LWIP_TCPIP_CORE_LOCKING */
  1994. #if LWIP_MPU_COMPATIBLE
  1995. /* MPU_COMPATIBLE copies the optval data, so check for max size here */
  1996. if (optlen > LWIP_SETGETSOCKOPT_MAXOPTLEN) {
  1997. sock_set_errno(sock, ENOBUFS);
  1998. return -1;
  1999. }
  2000. #endif /* LWIP_MPU_COMPATIBLE */
  2001. LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(data, sock);
  2002. LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).s = s;
  2003. LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).level = level;
  2004. LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optname = optname;
  2005. LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen = optlen;
  2006. #if LWIP_MPU_COMPATIBLE
  2007. MEMCPY(LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval, optval, optlen);
  2008. #else /* LWIP_MPU_COMPATIBLE */
  2009. LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval.pc = (const void*)optval;
  2010. #endif /* LWIP_MPU_COMPATIBLE */
  2011. LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err = 0;
  2012. #if LWIP_NETCONN_SEM_PER_THREAD
  2013. LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = LWIP_NETCONN_THREAD_SEM_GET();
  2014. #else
  2015. LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = &sock->conn->op_completed;
  2016. #endif
  2017. err = tcpip_callback(lwip_setsockopt_callback, &LWIP_SETGETSOCKOPT_DATA_VAR_REF(data));
  2018. if (err != ERR_OK) {
  2019. LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data);
  2020. sock_set_errno(sock, err_to_errno(err));
  2021. return -1;
  2022. }
  2023. sys_arch_sem_wait((sys_sem_t*)(LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem), 0);
  2024. /* maybe lwip_getsockopt_internal has changed err */
  2025. err = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err;
  2026. LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data);
  2027. #endif /* LWIP_TCPIP_CORE_LOCKING */
  2028. sock_set_errno(sock, err);
  2029. return err ? -1 : 0;
  2030. }
  2031. #if !LWIP_TCPIP_CORE_LOCKING
  2032. /** lwip_setsockopt_callback: only used without CORE_LOCKING
  2033. * to get into the tcpip_thread
  2034. */
  2035. static void
  2036. lwip_setsockopt_callback(void *arg)
  2037. {
  2038. struct lwip_setgetsockopt_data *data;
  2039. LWIP_ASSERT("arg != NULL", arg != NULL);
  2040. data = (struct lwip_setgetsockopt_data*)arg;
  2041. data->err = lwip_setsockopt_impl(data->s, data->level, data->optname,
  2042. #if LWIP_MPU_COMPATIBLE
  2043. data->optval,
  2044. #else /* LWIP_MPU_COMPATIBLE */
  2045. data->optval.pc,
  2046. #endif /* LWIP_MPU_COMPATIBLE */
  2047. data->optlen);
  2048. sys_sem_signal((sys_sem_t*)(data->completed_sem));
  2049. }
  2050. #endif /* LWIP_TCPIP_CORE_LOCKING */
  2051. /** lwip_setsockopt_impl: the actual implementation of setsockopt:
  2052. * same argument as lwip_setsockopt, either called directly or through callback
  2053. */
  2054. static u8_t
  2055. lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_t optlen)
  2056. {
  2057. u8_t err = 0;
  2058. struct lwip_sock *sock = tryget_socket(s);
  2059. if (!sock) {
  2060. return EBADF;
  2061. }
  2062. switch (level) {
  2063. /* Level: SOL_SOCKET */
  2064. case SOL_SOCKET:
  2065. switch (optname) {
  2066. /* SO_ACCEPTCONN is get-only */
  2067. /* The option flags */
  2068. case SO_BROADCAST:
  2069. case SO_KEEPALIVE:
  2070. #if SO_REUSE
  2071. case SO_REUSEADDR:
  2072. #endif /* SO_REUSE */
  2073. LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, int);
  2074. if (*(const int*)optval) {
  2075. ip_set_option(sock->conn->pcb.ip, optname);
  2076. } else {
  2077. ip_reset_option(sock->conn->pcb.ip, optname);
  2078. }
  2079. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, optname=0x%x, ..) -> %s\n",
  2080. s, optname, (*(const int*)optval?"on":"off")));
  2081. break;
  2082. /* SO_TYPE is get-only */
  2083. /* SO_ERROR is get-only */
  2084. #if LWIP_SO_SNDTIMEO
  2085. case SO_SNDTIMEO:
  2086. LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE);
  2087. netconn_set_sendtimeout(sock->conn, LWIP_SO_SNDRCVTIMEO_GET_MS(optval));
  2088. break;
  2089. #endif /* LWIP_SO_SNDTIMEO */
  2090. #if LWIP_SO_RCVTIMEO
  2091. case SO_RCVTIMEO:
  2092. LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE);
  2093. netconn_set_recvtimeout(sock->conn, (int)LWIP_SO_SNDRCVTIMEO_GET_MS(optval));
  2094. break;
  2095. #endif /* LWIP_SO_RCVTIMEO */
  2096. #if LWIP_SO_RCVBUF
  2097. case SO_RCVBUF:
  2098. LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, int);
  2099. netconn_set_recvbufsize(sock->conn, *(const int*)optval);
  2100. break;
  2101. #endif /* LWIP_SO_RCVBUF */
  2102. #if LWIP_SO_LINGER
  2103. case SO_LINGER:
  2104. {
  2105. const struct linger* linger = (const struct linger*)optval;
  2106. LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, struct linger);
  2107. if (linger->l_onoff) {
  2108. int lingersec = linger->l_linger;
  2109. if (lingersec < 0) {
  2110. return EINVAL;
  2111. }
  2112. if (lingersec > 0xFFFF) {
  2113. lingersec = 0xFFFF;
  2114. }
  2115. sock->conn->linger = (s16_t)lingersec;
  2116. } else {
  2117. sock->conn->linger = -1;
  2118. }
  2119. }
  2120. break;
  2121. #endif /* LWIP_SO_LINGER */
  2122. #if LWIP_UDP
  2123. case SO_NO_CHECK:
  2124. LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_UDP);
  2125. #if LWIP_UDPLITE
  2126. if ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0) {
  2127. /* this flag is only available for UDP, not for UDP lite */
  2128. return EAFNOSUPPORT;
  2129. }
  2130. #endif /* LWIP_UDPLITE */
  2131. if (*(const int*)optval) {
  2132. udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_NOCHKSUM);
  2133. } else {
  2134. udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_NOCHKSUM);
  2135. }
  2136. break;
  2137. #endif /* LWIP_UDP */
  2138. default:
  2139. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n",
  2140. s, optname));
  2141. err = ENOPROTOOPT;
  2142. break;
  2143. } /* switch (optname) */
  2144. break;
  2145. /* Level: IPPROTO_IP */
  2146. case IPPROTO_IP:
  2147. switch (optname) {
  2148. case IP_TTL:
  2149. LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, int);
  2150. sock->conn->pcb.ip->ttl = (u8_t)(*(const int*)optval);
  2151. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TTL, ..) -> %d\n",
  2152. s, sock->conn->pcb.ip->ttl));
  2153. break;
  2154. case IP_TOS:
  2155. LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, int);
  2156. sock->conn->pcb.ip->tos = (u8_t)(*(const int*)optval);
  2157. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TOS, ..)-> %d\n",
  2158. s, sock->conn->pcb.ip->tos));
  2159. break;
  2160. #if LWIP_MULTICAST_TX_OPTIONS
  2161. case IP_MULTICAST_TTL:
  2162. LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, u8_t, NETCONN_UDP);
  2163. udp_set_multicast_ttl(sock->conn->pcb.udp, (u8_t)(*(const u8_t*)optval));
  2164. break;
  2165. case IP_MULTICAST_IF:
  2166. {
  2167. ip4_addr_t if_addr;
  2168. LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, struct in_addr, NETCONN_UDP);
  2169. inet_addr_to_ip4addr(&if_addr, (const struct in_addr*)optval);
  2170. udp_set_multicast_netif_addr(sock->conn->pcb.udp, &if_addr);
  2171. }
  2172. break;
  2173. case IP_MULTICAST_LOOP:
  2174. LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, u8_t, NETCONN_UDP);
  2175. if (*(const u8_t*)optval) {
  2176. udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_MULTICAST_LOOP);
  2177. } else {
  2178. udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_MULTICAST_LOOP);
  2179. }
  2180. break;
  2181. #endif /* LWIP_MULTICAST_TX_OPTIONS */
  2182. #if LWIP_IGMP
  2183. case IP_ADD_MEMBERSHIP:
  2184. case IP_DROP_MEMBERSHIP:
  2185. {
  2186. /* If this is a TCP or a RAW socket, ignore these options. */
  2187. /* @todo: assign membership to this socket so that it is dropped when closing the socket */
  2188. err_t igmp_err;
  2189. const struct ip_mreq *imr = (const struct ip_mreq *)optval;
  2190. ip4_addr_t if_addr;
  2191. ip4_addr_t multi_addr;
  2192. LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, struct ip_mreq, NETCONN_UDP);
  2193. inet_addr_to_ip4addr(&if_addr, &imr->imr_interface);
  2194. inet_addr_to_ip4addr(&multi_addr, &imr->imr_multiaddr);
  2195. if (optname == IP_ADD_MEMBERSHIP) {
  2196. if (!lwip_socket_register_membership(s, &if_addr, &multi_addr)) {
  2197. /* cannot track membership (out of memory) */
  2198. err = ENOMEM;
  2199. igmp_err = ERR_OK;
  2200. } else {
  2201. igmp_err = igmp_joingroup(&if_addr, &multi_addr);
  2202. }
  2203. } else {
  2204. igmp_err = igmp_leavegroup(&if_addr, &multi_addr);
  2205. lwip_socket_unregister_membership(s, &if_addr, &multi_addr);
  2206. }
  2207. if (igmp_err != ERR_OK) {
  2208. err = EADDRNOTAVAIL;
  2209. }
  2210. }
  2211. break;
  2212. #endif /* LWIP_IGMP */
  2213. default:
  2214. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n",
  2215. s, optname));
  2216. err = ENOPROTOOPT;
  2217. break;
  2218. } /* switch (optname) */
  2219. break;
  2220. #if LWIP_TCP
  2221. /* Level: IPPROTO_TCP */
  2222. case IPPROTO_TCP:
  2223. /* Special case: all IPPROTO_TCP option take an int */
  2224. LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_TCP);
  2225. if (sock->conn->pcb.tcp->state == LISTEN) {
  2226. return EINVAL;
  2227. }
  2228. switch (optname) {
  2229. case TCP_NODELAY:
  2230. if (*(const int*)optval) {
  2231. tcp_nagle_disable(sock->conn->pcb.tcp);
  2232. } else {
  2233. tcp_nagle_enable(sock->conn->pcb.tcp);
  2234. }
  2235. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_NODELAY) -> %s\n",
  2236. s, (*(const int *)optval)?"on":"off") );
  2237. break;
  2238. case TCP_KEEPALIVE:
  2239. sock->conn->pcb.tcp->keep_idle = (u32_t)(*(const int*)optval);
  2240. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %"U32_F"\n",
  2241. s, sock->conn->pcb.tcp->keep_idle));
  2242. break;
  2243. #if LWIP_TCP_KEEPALIVE
  2244. case TCP_KEEPIDLE:
  2245. sock->conn->pcb.tcp->keep_idle = 1000*(u32_t)(*(const int*)optval);
  2246. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPIDLE) -> %"U32_F"\n",
  2247. s, sock->conn->pcb.tcp->keep_idle));
  2248. break;
  2249. case TCP_KEEPINTVL:
  2250. sock->conn->pcb.tcp->keep_intvl = 1000*(u32_t)(*(const int*)optval);
  2251. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPINTVL) -> %"U32_F"\n",
  2252. s, sock->conn->pcb.tcp->keep_intvl));
  2253. break;
  2254. case TCP_KEEPCNT:
  2255. sock->conn->pcb.tcp->keep_cnt = (u32_t)(*(const int*)optval);
  2256. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPCNT) -> %"U32_F"\n",
  2257. s, sock->conn->pcb.tcp->keep_cnt));
  2258. break;
  2259. #endif /* LWIP_TCP_KEEPALIVE */
  2260. default:
  2261. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n",
  2262. s, optname));
  2263. err = ENOPROTOOPT;
  2264. break;
  2265. } /* switch (optname) */
  2266. break;
  2267. #endif /* LWIP_TCP*/
  2268. #if LWIP_IPV6
  2269. /* Level: IPPROTO_IPV6 */
  2270. case IPPROTO_IPV6:
  2271. switch (optname) {
  2272. case IPV6_V6ONLY:
  2273. LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_TCP);
  2274. if (*(const int*)optval) {
  2275. netconn_set_ipv6only(sock->conn, 1);
  2276. } else {
  2277. netconn_set_ipv6only(sock->conn, 0);
  2278. }
  2279. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IPV6, IPV6_V6ONLY, ..) -> %d\n",
  2280. s, (netconn_get_ipv6only(sock->conn) ? 1 : 0)));
  2281. break;
  2282. default:
  2283. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IPV6, UNIMPL: optname=0x%x, ..)\n",
  2284. s, optname));
  2285. err = ENOPROTOOPT;
  2286. break;
  2287. } /* switch (optname) */
  2288. break;
  2289. #endif /* LWIP_IPV6 */
  2290. #if LWIP_UDP && LWIP_UDPLITE
  2291. /* Level: IPPROTO_UDPLITE */
  2292. case IPPROTO_UDPLITE:
  2293. /* Special case: all IPPROTO_UDPLITE option take an int */
  2294. LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, int);
  2295. /* If this is no UDP lite socket, ignore any options. */
  2296. if (!NETCONNTYPE_ISUDPLITE(netconn_type(sock->conn))) {
  2297. return ENOPROTOOPT;
  2298. }
  2299. switch (optname) {
  2300. case UDPLITE_SEND_CSCOV:
  2301. if ((*(const int*)optval != 0) && ((*(const int*)optval < 8) || (*(const int*)optval > 0xffff))) {
  2302. /* don't allow illegal values! */
  2303. sock->conn->pcb.udp->chksum_len_tx = 8;
  2304. } else {
  2305. sock->conn->pcb.udp->chksum_len_tx = (u16_t)*(const int*)optval;
  2306. }
  2307. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) -> %d\n",
  2308. s, (*(const int*)optval)) );
  2309. break;
  2310. case UDPLITE_RECV_CSCOV:
  2311. if ((*(const int*)optval != 0) && ((*(const int*)optval < 8) || (*(const int*)optval > 0xffff))) {
  2312. /* don't allow illegal values! */
  2313. sock->conn->pcb.udp->chksum_len_rx = 8;
  2314. } else {
  2315. sock->conn->pcb.udp->chksum_len_rx = (u16_t)*(const int*)optval;
  2316. }
  2317. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) -> %d\n",
  2318. s, (*(const int*)optval)) );
  2319. break;
  2320. default:
  2321. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n",
  2322. s, optname));
  2323. err = ENOPROTOOPT;
  2324. break;
  2325. } /* switch (optname) */
  2326. break;
  2327. #endif /* LWIP_UDP */
  2328. /* Level: IPPROTO_RAW */
  2329. case IPPROTO_RAW:
  2330. switch (optname) {
  2331. #if LWIP_IPV6 && LWIP_RAW
  2332. case IPV6_CHECKSUM:
  2333. /* It should not be possible to disable the checksum generation with ICMPv6
  2334. * as per RFC 3542 chapter 3.1 */
  2335. if(sock->conn->pcb.raw->protocol == IPPROTO_ICMPV6) {
  2336. return EINVAL;
  2337. }
  2338. LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_RAW);
  2339. if (*(const int *)optval < 0) {
  2340. sock->conn->pcb.raw->chksum_reqd = 0;
  2341. } else if (*(const int *)optval & 1) {
  2342. /* Per RFC3542, odd offsets are not allowed */
  2343. return EINVAL;
  2344. } else {
  2345. sock->conn->pcb.raw->chksum_reqd = 1;
  2346. sock->conn->pcb.raw->chksum_offset = (u16_t)*(const int *)optval;
  2347. }
  2348. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_RAW, IPV6_CHECKSUM, ..) -> %d\n",
  2349. s, sock->conn->pcb.raw->chksum_reqd));
  2350. break;
  2351. #endif /* LWIP_IPV6 && LWIP_RAW */
  2352. default:
  2353. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_RAW, UNIMPL: optname=0x%x, ..)\n",
  2354. s, optname));
  2355. err = ENOPROTOOPT;
  2356. break;
  2357. } /* switch (optname) */
  2358. break;
  2359. default:
  2360. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n",
  2361. s, level, optname));
  2362. err = ENOPROTOOPT;
  2363. break;
  2364. } /* switch (level) */
  2365. return err;
  2366. }
  2367. int
  2368. lwip_ioctl(int s, long cmd, void *argp)
  2369. {
  2370. struct lwip_sock *sock = get_socket(s);
  2371. u8_t val;
  2372. #if LWIP_SO_RCVBUF
  2373. u16_t buflen = 0;
  2374. int recv_avail;
  2375. #endif /* LWIP_SO_RCVBUF */
  2376. if (!sock) {
  2377. return -1;
  2378. }
  2379. switch (cmd) {
  2380. #if LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE
  2381. case FIONREAD:
  2382. if (!argp) {
  2383. sock_set_errno(sock, EINVAL);
  2384. return -1;
  2385. }
  2386. #if LWIP_FIONREAD_LINUXMODE
  2387. if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) {
  2388. struct pbuf *p;
  2389. if (sock->lastdata) {
  2390. p = ((struct netbuf *)sock->lastdata)->p;
  2391. *((int*)argp) = p->tot_len - sock->lastoffset;
  2392. } else {
  2393. struct netbuf *rxbuf;
  2394. err_t err;
  2395. if (sock->rcvevent <= 0) {
  2396. *((int*)argp) = 0;
  2397. } else {
  2398. err = netconn_recv(sock->conn, &rxbuf);
  2399. if (err != ERR_OK) {
  2400. *((int*)argp) = 0;
  2401. } else {
  2402. sock->lastdata = rxbuf;
  2403. sock->lastoffset = 0;
  2404. *((int*)argp) = rxbuf->p->tot_len;
  2405. }
  2406. }
  2407. }
  2408. return 0;
  2409. }
  2410. #endif /* LWIP_FIONREAD_LINUXMODE */
  2411. #if LWIP_SO_RCVBUF
  2412. /* we come here if either LWIP_FIONREAD_LINUXMODE==0 or this is a TCP socket */
  2413. SYS_ARCH_GET(sock->conn->recv_avail, recv_avail);
  2414. if (recv_avail < 0) {
  2415. recv_avail = 0;
  2416. }
  2417. *((int*)argp) = recv_avail;
  2418. /* Check if there is data left from the last recv operation. /maq 041215 */
  2419. if (sock->lastdata) {
  2420. struct pbuf *p = (struct pbuf *)sock->lastdata;
  2421. if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) {
  2422. p = ((struct netbuf *)p)->p;
  2423. }
  2424. buflen = p->tot_len;
  2425. buflen -= sock->lastoffset;
  2426. *((int*)argp) += buflen;
  2427. }
  2428. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %"U16_F"\n", s, argp, *((u16_t*)argp)));
  2429. sock_set_errno(sock, 0);
  2430. return 0;
  2431. #else /* LWIP_SO_RCVBUF */
  2432. break;
  2433. #endif /* LWIP_SO_RCVBUF */
  2434. #endif /* LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE */
  2435. case (long)FIONBIO:
  2436. val = 0;
  2437. if (argp && *(u32_t*)argp) {
  2438. val = 1;
  2439. }
  2440. netconn_set_nonblocking(sock->conn, val);
  2441. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONBIO, %d)\n", s, val));
  2442. sock_set_errno(sock, 0);
  2443. return 0;
  2444. default:
  2445. break;
  2446. } /* switch (cmd) */
  2447. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, UNIMPL: 0x%lx, %p)\n", s, cmd, argp));
  2448. sock_set_errno(sock, ENOSYS); /* not yet implemented */
  2449. return -1;
  2450. }
  2451. /** A minimal implementation of fcntl.
  2452. * Currently only the commands F_GETFL and F_SETFL are implemented.
  2453. * Only the flag O_NONBLOCK is implemented.
  2454. */
  2455. int
  2456. lwip_fcntl(int s, int cmd, int val)
  2457. {
  2458. struct lwip_sock *sock = get_socket(s);
  2459. int ret = -1;
  2460. if (!sock) {
  2461. return -1;
  2462. }
  2463. switch (cmd) {
  2464. case F_GETFL:
  2465. ret = netconn_is_nonblocking(sock->conn) ? O_NONBLOCK : 0;
  2466. sock_set_errno(sock, 0);
  2467. break;
  2468. case F_SETFL:
  2469. if ((val & ~O_NONBLOCK) == 0) {
  2470. /* only O_NONBLOCK, all other bits are zero */
  2471. netconn_set_nonblocking(sock->conn, val & O_NONBLOCK);
  2472. ret = 0;
  2473. sock_set_errno(sock, 0);
  2474. } else {
  2475. sock_set_errno(sock, ENOSYS); /* not yet implemented */
  2476. }
  2477. break;
  2478. default:
  2479. LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_fcntl(%d, UNIMPL: %d, %d)\n", s, cmd, val));
  2480. sock_set_errno(sock, ENOSYS); /* not yet implemented */
  2481. break;
  2482. }
  2483. return ret;
  2484. }
  2485. #if LWIP_IGMP
  2486. /** Register a new IGMP membership. On socket close, the membership is dropped automatically.
  2487. *
  2488. * ATTENTION: this function is called from tcpip_thread (or under CORE_LOCK).
  2489. *
  2490. * @return 1 on success, 0 on failure
  2491. */
  2492. static int
  2493. lwip_socket_register_membership(int s, const ip4_addr_t *if_addr, const ip4_addr_t *multi_addr)
  2494. {
  2495. struct lwip_sock *sock = get_socket(s);
  2496. int i;
  2497. if (!sock) {
  2498. return 0;
  2499. }
  2500. for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) {
  2501. if (socket_ipv4_multicast_memberships[i].sock == NULL) {
  2502. socket_ipv4_multicast_memberships[i].sock = sock;
  2503. ip4_addr_copy(socket_ipv4_multicast_memberships[i].if_addr, *if_addr);
  2504. ip4_addr_copy(socket_ipv4_multicast_memberships[i].multi_addr, *multi_addr);
  2505. return 1;
  2506. }
  2507. }
  2508. return 0;
  2509. }
  2510. /** Unregister a previously registered membership. This prevents dropping the membership
  2511. * on socket close.
  2512. *
  2513. * ATTENTION: this function is called from tcpip_thread (or under CORE_LOCK).
  2514. */
  2515. static void
  2516. lwip_socket_unregister_membership(int s, const ip4_addr_t *if_addr, const ip4_addr_t *multi_addr)
  2517. {
  2518. struct lwip_sock *sock = get_socket(s);
  2519. int i;
  2520. if (!sock) {
  2521. return;
  2522. }
  2523. for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) {
  2524. if ((socket_ipv4_multicast_memberships[i].sock == sock) &&
  2525. ip4_addr_cmp(&socket_ipv4_multicast_memberships[i].if_addr, if_addr) &&
  2526. ip4_addr_cmp(&socket_ipv4_multicast_memberships[i].multi_addr, multi_addr)) {
  2527. socket_ipv4_multicast_memberships[i].sock = NULL;
  2528. ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].if_addr);
  2529. ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].multi_addr);
  2530. return;
  2531. }
  2532. }
  2533. }
  2534. /** Drop all memberships of a socket that were not dropped explicitly via setsockopt.
  2535. *
  2536. * ATTENTION: this function is NOT called from tcpip_thread (or under CORE_LOCK).
  2537. */
  2538. static void
  2539. lwip_socket_drop_registered_memberships(int s)
  2540. {
  2541. struct lwip_sock *sock = get_socket(s);
  2542. int i;
  2543. if (!sock) {
  2544. return;
  2545. }
  2546. for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) {
  2547. if (socket_ipv4_multicast_memberships[i].sock == sock) {
  2548. ip_addr_t multi_addr, if_addr;
  2549. ip_addr_copy_from_ip4(multi_addr, socket_ipv4_multicast_memberships[i].multi_addr);
  2550. ip_addr_copy_from_ip4(if_addr, socket_ipv4_multicast_memberships[i].if_addr);
  2551. socket_ipv4_multicast_memberships[i].sock = NULL;
  2552. ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].if_addr);
  2553. ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].multi_addr);
  2554. netconn_join_leave_group(sock->conn, &multi_addr, &if_addr, NETCONN_LEAVE);
  2555. }
  2556. }
  2557. }
  2558. #endif /* LWIP_IGMP */
  2559. #endif /* LWIP_SOCKET */