netdev_ioctl.c 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809
  1. /****************************************************************************
  2. * net/netdev/netdev_ioctl.c
  3. *
  4. * Copyright (C) 2007-2012, 2015-2019 Gregory Nutt. All rights reserved.
  5. * Author: Gregory Nutt <gnutt@nuttx.org>
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in
  15. * the documentation and/or other materials provided with the
  16. * distribution.
  17. * 3. Neither the name NuttX nor the names of its contributors may be
  18. * used to endorse or promote products derived from this software
  19. * without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  24. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  25. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  26. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  27. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  28. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  29. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  31. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  32. * POSSIBILITY OF SUCH DAMAGE.
  33. *
  34. ****************************************************************************/
  35. /****************************************************************************
  36. * Included Files
  37. ****************************************************************************/
  38. #include <nuttx/config.h>
  39. #include <sys/socket.h>
  40. #include <sys/ioctl.h>
  41. #include <string.h>
  42. #include <assert.h>
  43. #include <errno.h>
  44. #include <debug.h>
  45. #include <nuttx/net/net.h>
  46. #include <nuttx/net/ip.h>
  47. #include <net/if.h>
  48. #include <net/route.h>
  49. #include <net/ethernet.h>
  50. #include <netinet/in.h>
  51. #include <nuttx/net/netdev.h>
  52. #include <nuttx/net/radiodev.h>
  53. #include <nuttx/net/arp.h>
  54. #ifdef CONFIG_NET_6LOWPAN
  55. # include <nuttx/net/sixlowpan.h>
  56. #endif
  57. #include <sys/sockio.h>
  58. #include <nuttx/net/igmp.h>
  59. #ifdef CONFIG_NETDEV_WIRELESS_IOCTL
  60. # include <nuttx/wireless/wireless.h>
  61. #endif
  62. #ifdef CONFIG_WIRELESS_BLUETOOTH
  63. # include <nuttx/wireless/bluetooth/bt_ioctl.h>
  64. #endif
  65. #ifdef CONFIG_WIRELESS_IEEE802154
  66. # include <nuttx/wireless/ieee802154/ieee802154_mac.h>
  67. #endif
  68. #ifdef CONFIG_WIRELESS_PKTRADIO
  69. # include <nuttx/wireless/pktradio.h>
  70. #endif
  71. #include "arp/arp.h"
  72. #include "socket/socket.h"
  73. #include "netdev/netdev.h"
  74. #include "devif/devif.h"
  75. #include "igmp/igmp.h"
  76. #include "icmpv6/icmpv6.h"
  77. #include "route/route.h"
  78. /****************************************************************************
  79. * Pre-processor Definitions
  80. ****************************************************************************/
  81. /* Configuration */
  82. #undef HAVE_WRITABLE_IPv4ROUTE
  83. #undef HAVE_WRITABLE_IPv6ROUTE
  84. #ifdef CONFIG_NET_ROUTE
  85. # if defined(CONFIG_NET_IPv4) && !defined(CONFIG_ROUTE_IPv4_ROMROUTE)
  86. # define HAVE_WRITABLE_IPv4ROUTE 1
  87. # endif
  88. # if defined(CONFIG_NET_IPv6) && !defined(CONFIG_ROUTE_IPv6_ROMROUTE)
  89. # define HAVE_WRITABLE_IPv6ROUTE 1
  90. # endif
  91. #endif
  92. #undef HAVE_IEEE802154_IOCTL
  93. #undef HAVE_PKTRADIO_IOCTL
  94. #undef HAVE_BLUETOOTH_IOCTL
  95. #ifdef CONFIG_NETDEV_IOCTL
  96. /* IEEE 802.15.4 6LoWPAN or raw packet support */
  97. #if defined(CONFIG_NET_IEEE802154) || (defined(CONFIG_NET_6LOWPAN) && \
  98. defined(CONFIG_WIRELESS_IEEE802154))
  99. # define HAVE_IEEE802154_IOCTL 1
  100. #endif
  101. /* pktradio raw packet support not implemented */
  102. #if defined(CONFIG_NET_6LOWPAN) && defined(CONFIG_WIRELESS_PKTRADIO)
  103. # define HAVE_PKTRADIO_IOCTL 1
  104. #endif
  105. /* Bluetooth 6LoWPAN support not implemented */
  106. #if defined(CONFIG_NET_BLUETOOTH)
  107. # define HAVE_BLUETOOTH_IOCTL 1
  108. #endif
  109. #endif /* CONFIG_NETDEV_IOCTL */
  110. /* This is really kind of bogus.. When asked for an IP address, this is
  111. * family that is returned in the ifr structure. Probably could just skip
  112. * this since the address family has nothing to do with the Ethernet address.
  113. */
  114. #ifdef CONFIG_NET_IPv6
  115. # define AF_INETX AF_INET6
  116. #else
  117. # define AF_INETX AF_INET
  118. #endif
  119. /****************************************************************************
  120. * Private Functions
  121. ****************************************************************************/
  122. /****************************************************************************
  123. * Name: ioctl_add_ipv4route
  124. *
  125. * Description:
  126. * Add an IPv4 route to the routing table.
  127. *
  128. * Input Parameters:
  129. * rentry - Describes the route to be added
  130. *
  131. ****************************************************************************/
  132. #ifdef HAVE_WRITABLE_IPv4ROUTE
  133. static int ioctl_add_ipv4route(FAR struct rtentry *rtentry)
  134. {
  135. FAR struct sockaddr_in *addr;
  136. in_addr_t target;
  137. in_addr_t netmask;
  138. in_addr_t router;
  139. addr = (FAR struct sockaddr_in *)rtentry->rt_target;
  140. target = (in_addr_t)addr->sin_addr.s_addr;
  141. addr = (FAR struct sockaddr_in *)rtentry->rt_netmask;
  142. netmask = (in_addr_t)addr->sin_addr.s_addr;
  143. /* The router is an optional argument */
  144. if (rtentry->rt_router)
  145. {
  146. addr = (FAR struct sockaddr_in *)rtentry->rt_router;
  147. router = (in_addr_t)addr->sin_addr.s_addr;
  148. }
  149. else
  150. {
  151. router = 0;
  152. }
  153. return net_addroute_ipv4(target, netmask, router);
  154. }
  155. #endif /* HAVE_WRITABLE_IPv4ROUTE */
  156. /****************************************************************************
  157. * Name: ioctl_add_ipv6route
  158. *
  159. * Description:
  160. * Add an IPv6 route to the routing table.
  161. *
  162. * Input Parameters:
  163. * rentry - Describes the route to be added
  164. *
  165. ****************************************************************************/
  166. #ifdef HAVE_WRITABLE_IPv6ROUTE
  167. static int ioctl_add_ipv6route(FAR struct rtentry *rtentry)
  168. {
  169. FAR struct sockaddr_in6 *target;
  170. FAR struct sockaddr_in6 *netmask;
  171. net_ipv6addr_t router;
  172. target = (FAR struct sockaddr_in6 *)rtentry->rt_target;
  173. netmask = (FAR struct sockaddr_in6 *)rtentry->rt_netmask;
  174. /* The router is an optional argument */
  175. if (rtentry->rt_router)
  176. {
  177. FAR struct sockaddr_in6 *addr;
  178. addr = (FAR struct sockaddr_in6 *)rtentry->rt_router;
  179. net_ipv6addr_copy(router, addr->sin6_addr.s6_addr16);
  180. }
  181. else
  182. {
  183. net_ipv6addr_copy(router, in6addr_any.s6_addr16);
  184. }
  185. return net_addroute_ipv6(target->sin6_addr.s6_addr16, netmask->sin6_addr.s6_addr16, router);
  186. }
  187. #endif /* HAVE_WRITABLE_IPv6ROUTE */
  188. /****************************************************************************
  189. * Name: ioctl_del_ipv4route
  190. *
  191. * Description:
  192. * Delete an IPv4 route to the routing table.
  193. *
  194. * Input Parameters:
  195. * rentry - Describes the route to be deleted
  196. *
  197. ****************************************************************************/
  198. #ifdef HAVE_WRITABLE_IPv4ROUTE
  199. static int ioctl_del_ipv4route(FAR struct rtentry *rtentry)
  200. {
  201. FAR struct sockaddr_in *addr;
  202. in_addr_t target;
  203. in_addr_t netmask;
  204. addr = (FAR struct sockaddr_in *)rtentry->rt_target;
  205. target = (in_addr_t)addr->sin_addr.s_addr;
  206. addr = (FAR struct sockaddr_in *)rtentry->rt_netmask;
  207. netmask = (in_addr_t)addr->sin_addr.s_addr;
  208. return net_delroute_ipv4(target, netmask);
  209. }
  210. #endif /* HAVE_WRITABLE_IPv4ROUTE */
  211. /****************************************************************************
  212. * Name: ioctl_del_ipv6route
  213. *
  214. * Description:
  215. * Delete an IPv6 route to the routing table.
  216. *
  217. * Input Parameters:
  218. * rentry - Describes the route to be deleted
  219. *
  220. ****************************************************************************/
  221. #ifdef HAVE_WRITABLE_IPv6ROUTE
  222. static int ioctl_del_ipv6route(FAR struct rtentry *rtentry)
  223. {
  224. FAR struct sockaddr_in6 *target;
  225. FAR struct sockaddr_in6 *netmask;
  226. target = (FAR struct sockaddr_in6 *)rtentry->rt_target;
  227. netmask = (FAR struct sockaddr_in6 *)rtentry->rt_netmask;
  228. return net_delroute_ipv6(target->sin6_addr.s6_addr16, netmask->sin6_addr.s6_addr16);
  229. }
  230. #endif /* HAVE_WRITABLE_IPv6ROUTE */
  231. /****************************************************************************
  232. * Name: ioctl_get_ipv4addr
  233. *
  234. * Description:
  235. * Copy IP addresses from device structure to user memory.
  236. *
  237. * Input Parameters:
  238. * outaddr - Pointer to the user-provided memory to receive the address.
  239. * inaddr - The source IP address in the device structure.
  240. *
  241. ****************************************************************************/
  242. #ifdef CONFIG_NET_IPv4
  243. static void ioctl_get_ipv4addr(FAR struct sockaddr *outaddr,
  244. in_addr_t inaddr)
  245. {
  246. FAR struct sockaddr_in *dest = (FAR struct sockaddr_in *)outaddr;
  247. dest->sin_family = AF_INET;
  248. dest->sin_port = 0;
  249. dest->sin_addr.s_addr = inaddr;
  250. }
  251. #endif
  252. /****************************************************************************
  253. * Name: ioctl_get_ipv4broadcast
  254. *
  255. * Description:
  256. * Return the sub-net broadcast address to user memory.
  257. *
  258. * Input Parameters:
  259. * outaddr - Pointer to the user-provided memory to receive the address.
  260. * inaddr - The source IP address in the device structure.
  261. * netmask - The netmask address mask in the device structure.
  262. *
  263. ****************************************************************************/
  264. #ifdef CONFIG_NET_IPv4
  265. static void inline ioctl_get_ipv4broadcast(FAR struct sockaddr *outaddr,
  266. in_addr_t inaddr, in_addr_t netmask)
  267. {
  268. FAR struct sockaddr_in *dest = (FAR struct sockaddr_in *)outaddr;
  269. dest->sin_family = AF_INET;
  270. dest->sin_port = 0;
  271. dest->sin_addr.s_addr = net_ipv4addr_broadcast(inaddr, netmask);
  272. }
  273. #endif
  274. /****************************************************************************
  275. * Name: ioctl_get_ipv6addr
  276. *
  277. * Description:
  278. * Copy IP addresses from device structure to user memory.
  279. *
  280. * Input Parameters:
  281. * outaddr - Pointer to the user-provided memory to receive the address.
  282. * inaddr - The source IP adress in the device structure.
  283. *
  284. ****************************************************************************/
  285. #ifdef CONFIG_NET_IPv6
  286. static void ioctl_get_ipv6addr(FAR struct sockaddr_storage *outaddr,
  287. FAR const net_ipv6addr_t inaddr)
  288. {
  289. FAR struct sockaddr_in6 *dest = (FAR struct sockaddr_in6 *)outaddr;
  290. dest->sin6_family = AF_INET6;
  291. dest->sin6_port = 0;
  292. memcpy(dest->sin6_addr.in6_u.u6_addr8, inaddr, 16);
  293. }
  294. #endif
  295. /****************************************************************************
  296. * Name: ioctl_set_ipv4addr
  297. *
  298. * Description:
  299. * Copy IP addresses from user memory into the device structure
  300. *
  301. * Input Parameters:
  302. * outaddr - Pointer to the source IP address in the device structure.
  303. * inaddr - Pointer to the user-provided memory to containing the new IP
  304. * address.
  305. *
  306. ****************************************************************************/
  307. #ifdef CONFIG_NET_IPv4
  308. static void ioctl_set_ipv4addr(FAR in_addr_t *outaddr,
  309. FAR const struct sockaddr *inaddr)
  310. {
  311. FAR const struct sockaddr_in *src = (FAR const struct sockaddr_in *)inaddr;
  312. *outaddr = src->sin_addr.s_addr;
  313. }
  314. #endif
  315. /****************************************************************************
  316. * Name: ioctl_set_ipv6addr
  317. *
  318. * Description:
  319. * Copy IP addresses from user memory into the device structure
  320. *
  321. * Input Parameters:
  322. * outaddr - Pointer to the source IP address in the device structure.
  323. * inaddr - Pointer to the user-provided memory to containing the new IP
  324. * address.
  325. *
  326. ****************************************************************************/
  327. #ifdef CONFIG_NET_IPv6
  328. static void ioctl_set_ipv6addr(FAR net_ipv6addr_t outaddr,
  329. FAR const struct sockaddr_storage *inaddr)
  330. {
  331. FAR const struct sockaddr_in6 *src = (FAR const struct sockaddr_in6 *)inaddr;
  332. memcpy(outaddr, src->sin6_addr.in6_u.u6_addr8, 16);
  333. }
  334. #endif
  335. /****************************************************************************
  336. * Name: netdev_bluetooth_ioctl
  337. *
  338. * Description:
  339. * Perform Bluetooth network device specific operations.
  340. *
  341. * Input Parameters:
  342. * psock - Socket structure
  343. * dev - Ethernet driver device structure
  344. * cmd - The ioctl command
  345. * req - The argument of the ioctl cmd
  346. *
  347. * Returned Value:
  348. * >=0 on success (positive non-zero values are cmd-specific)
  349. * Negated errno returned on failure.
  350. *
  351. ****************************************************************************/
  352. #ifdef HAVE_BLUETOOTH_IOCTL
  353. static int netdev_bluetooth_ioctl(FAR struct socket *psock, int cmd,
  354. unsigned long arg)
  355. {
  356. FAR struct net_driver_s *dev;
  357. FAR char *ifname;
  358. int ret = -EINVAL;
  359. if (arg != 0ul)
  360. {
  361. if (WL_IBLUETOOTHCMD(cmd))
  362. {
  363. /* Get the name of the Bluetooth device to receive the IOCTL
  364. * command
  365. */
  366. FAR struct btreq_s *btreq =
  367. (FAR struct btreq_s *)((uintptr_t)arg);
  368. ifname = btreq->btr_name;
  369. }
  370. else
  371. {
  372. /* Not a Bluetooth IOCTL command */
  373. return -ENOTTY;
  374. }
  375. /* Find the device with this name */
  376. dev = netdev_findbyname(ifname);
  377. ret = -ENODEV;
  378. if (dev != NULL && dev->d_lltype == NET_LL_BLUETOOTH)
  379. {
  380. /* Perform the device IOCTL */
  381. ret = dev->d_ioctl(dev, cmd, arg);
  382. }
  383. }
  384. return ret;
  385. }
  386. #endif
  387. /****************************************************************************
  388. * Name: netdev_iee802154_ioctl
  389. *
  390. * Description:
  391. * Perform IEEE802.15.4 network device specific operations.
  392. *
  393. * Input Parameters:
  394. * psock - Socket structure
  395. * dev - Ethernet driver device structure
  396. * cmd - The ioctl command
  397. * req - The argument of the ioctl cmd
  398. *
  399. * Returned Value:
  400. * >=0 on success (positive non-zero values are cmd-specific)
  401. * Negated errno returned on failure.
  402. *
  403. ****************************************************************************/
  404. #ifdef HAVE_IEEE802154_IOCTL
  405. static int netdev_iee802154_ioctl(FAR struct socket *psock, int cmd,
  406. unsigned long arg)
  407. {
  408. FAR struct net_driver_s *dev;
  409. FAR char *ifname;
  410. int ret = -ENOTTY;
  411. if (arg != 0ul)
  412. {
  413. if (_MAC802154IOCVALID(cmd))
  414. {
  415. /* Get the IEEE802.15.4 MAC device to receive the radio IOCTL
  416. * command
  417. */
  418. FAR struct ieee802154_netmac_s *netmac =
  419. (FAR struct ieee802154_netmac_s *)((uintptr_t)arg);
  420. ifname = netmac->ifr_name;
  421. }
  422. else
  423. {
  424. /* Not an EEE802.15.4 MAC IOCTL command */
  425. return -ENOTTY;
  426. }
  427. /* Find the device with this name */
  428. dev = netdev_findbyname(ifname);
  429. if (dev != NULL && dev->d_lltype == NET_LL_IEEE802154)
  430. {
  431. /* Perform the device IOCTL */
  432. ret = dev->d_ioctl(dev, cmd, arg);
  433. }
  434. }
  435. return ret;
  436. }
  437. #endif /* HAVE_IEEE802154_IOCTL */
  438. /****************************************************************************
  439. * Name: netdev_pktradio_ioctl
  440. *
  441. * Description:
  442. * Perform non-IEEE802.15.4 packet radio network device specific operations.
  443. *
  444. * Input Parameters:
  445. * psock - Socket structure
  446. * dev - Ethernet driver device structure
  447. * cmd - The ioctl command
  448. * req - The argument of the ioctl cmd
  449. *
  450. * Returned Value:
  451. * >=0 on success (positive non-zero values are cmd-specific)
  452. * Negated errno returned on failure.
  453. *
  454. ****************************************************************************/
  455. #ifdef HAVE_PKTRADIO_IOCTL
  456. static int netdev_pktradio_ioctl(FAR struct socket *psock, int cmd,
  457. unsigned long arg)
  458. {
  459. FAR struct net_driver_s *dev;
  460. FAR char *ifname;
  461. int ret = -ENOTTY;
  462. if (arg != 0ul)
  463. {
  464. if (WL_ISPKTRADIOCMD(cmd))
  465. {
  466. /* Get the packet radio device to receive the radio IOCTL
  467. * command
  468. */
  469. FAR struct pktradio_ifreq_s *cmddata =
  470. (FAR struct pktradio_ifreq_s *)((uintptr_t)arg);
  471. ifname = cmddata->pifr_name;
  472. }
  473. else
  474. {
  475. /* Not a packet radio IOCTL command */
  476. nwarn("WARNING: Not a packet radio IOCTL command: %d\n", cmd);
  477. return -ENOTTY;
  478. }
  479. /* Find the device with this name */
  480. dev = netdev_findbyname(ifname);
  481. if (dev != NULL && dev->d_lltype == NET_LL_PKTRADIO)
  482. {
  483. /* Perform the device IOCTL */
  484. ret = dev->d_ioctl(dev, cmd, arg);
  485. }
  486. }
  487. return ret;
  488. }
  489. #endif /* HAVE_PKTRADIO_IOCTL */
  490. /****************************************************************************
  491. * Name: netdev_wifr_ioctl
  492. *
  493. * Description:
  494. * Perform wireless network device specific operations.
  495. *
  496. * Input Parameters:
  497. * psock Socket structure
  498. * dev Ethernet driver device structure
  499. * cmd The ioctl command
  500. * req The argument of the ioctl cmd
  501. *
  502. * Returned Value:
  503. * >=0 on success (positive non-zero values are cmd-specific)
  504. * Negated errno returned on failure.
  505. *
  506. ****************************************************************************/
  507. #if defined(CONFIG_NETDEV_IOCTL) && defined(CONFIG_NETDEV_WIRELESS_IOCTL)
  508. static int netdev_wifr_ioctl(FAR struct socket *psock, int cmd,
  509. FAR struct iwreq *req)
  510. {
  511. FAR struct net_driver_s *dev;
  512. int ret = -ENOTTY;
  513. /* Verify that this is a valid wireless network IOCTL command */
  514. if (_WLIOCVALID(cmd) && (unsigned)_IOC_NR(cmd) <= WL_NNETCMDS)
  515. {
  516. /* Get the wireless device associated with the IOCTL command */
  517. dev = netdev_findbyname(req->ifr_name);
  518. if (dev != NULL)
  519. {
  520. /* Just forward the IOCTL to the wireless driver */
  521. ret = dev->d_ioctl(dev, cmd, ((unsigned long)(uintptr_t)req));
  522. }
  523. }
  524. return ret;
  525. }
  526. #endif
  527. /****************************************************************************
  528. * Name: netdev_ifr_dev
  529. *
  530. * Description:
  531. * Verify the struct ifreq and get the Ethernet device.
  532. *
  533. * Input Parameters:
  534. * req - The argument of the ioctl cmd
  535. *
  536. * Returned Value:
  537. * A pointer to the driver structure on success; NULL on failure.
  538. *
  539. ****************************************************************************/
  540. static FAR struct net_driver_s *netdev_ifr_dev(FAR struct ifreq *req)
  541. {
  542. if (req != NULL)
  543. {
  544. /* Find the network device associated with the device name
  545. * in the request data.
  546. */
  547. return netdev_findbyname(req->ifr_name);
  548. }
  549. return NULL;
  550. }
  551. /****************************************************************************
  552. * Name: netdev_ifr_ioctl
  553. *
  554. * Description:
  555. * Perform network device specific operations.
  556. *
  557. * Input Parameters:
  558. * psock Socket structure
  559. * cmd The ioctl command
  560. * req The argument of the ioctl cmd
  561. *
  562. * Returned Value:
  563. * >=0 on success (positive non-zero values are cmd-specific)
  564. * Negated errno returned on failure.
  565. *
  566. ****************************************************************************/
  567. static int netdev_ifr_ioctl(FAR struct socket *psock, int cmd,
  568. FAR struct ifreq *req)
  569. {
  570. FAR struct net_driver_s *dev;
  571. int ret = -EINVAL;
  572. ninfo("cmd: %d\n", cmd);
  573. /* Execute the command */
  574. switch (cmd)
  575. {
  576. #ifdef CONFIG_NET_IPv4
  577. case SIOCGIFADDR: /* Get IP address */
  578. {
  579. dev = netdev_ifr_dev(req);
  580. if (dev)
  581. {
  582. ioctl_get_ipv4addr(&req->ifr_addr, dev->d_ipaddr);
  583. ret = OK;
  584. }
  585. }
  586. break;
  587. #endif
  588. #ifdef CONFIG_NET_IPv4
  589. case SIOCSIFADDR: /* Set IP address */
  590. {
  591. dev = netdev_ifr_dev(req);
  592. if (dev)
  593. {
  594. ioctl_set_ipv4addr(&dev->d_ipaddr, &req->ifr_addr);
  595. ret = OK;
  596. }
  597. }
  598. break;
  599. #endif
  600. #ifdef CONFIG_NET_IPv4
  601. case SIOCGIFDSTADDR: /* Get P-to-P address */
  602. {
  603. dev = netdev_ifr_dev(req);
  604. if (dev)
  605. {
  606. ioctl_get_ipv4addr(&req->ifr_dstaddr, dev->d_draddr);
  607. ret = OK;
  608. }
  609. }
  610. break;
  611. #endif
  612. #ifdef CONFIG_NET_IPv4
  613. case SIOCSIFDSTADDR: /* Set P-to-P address */
  614. {
  615. dev = netdev_ifr_dev(req);
  616. if (dev)
  617. {
  618. ioctl_set_ipv4addr(&dev->d_draddr, &req->ifr_dstaddr);
  619. ret = OK;
  620. }
  621. }
  622. break;
  623. #endif
  624. #ifdef CONFIG_NET_IPv4
  625. case SIOCGIFBRDADDR: /* Get broadcast IP address */
  626. {
  627. dev = netdev_ifr_dev(req);
  628. if (dev)
  629. {
  630. ioctl_get_ipv4broadcast(&req->ifr_broadaddr, dev->d_ipaddr,
  631. dev->d_netmask);
  632. ret = OK;
  633. }
  634. }
  635. break;
  636. #endif
  637. #ifdef CONFIG_NET_IPv4
  638. case SIOCSIFBRDADDR: /* Set broadcast IP address */
  639. {
  640. ret = -ENOSYS;
  641. }
  642. break;
  643. #endif
  644. #ifdef CONFIG_NET_IPv4
  645. case SIOCGIFNETMASK: /* Get network mask */
  646. {
  647. dev = netdev_ifr_dev(req);
  648. if (dev)
  649. {
  650. ioctl_get_ipv4addr(&req->ifr_addr, dev->d_netmask);
  651. ret = OK;
  652. }
  653. }
  654. break;
  655. #endif
  656. #ifdef CONFIG_NET_IPv4
  657. case SIOCSIFNETMASK: /* Set network mask */
  658. {
  659. dev = netdev_ifr_dev(req);
  660. if (dev)
  661. {
  662. ioctl_set_ipv4addr(&dev->d_netmask, &req->ifr_addr);
  663. ret = OK;
  664. }
  665. }
  666. break;
  667. #endif
  668. #ifdef CONFIG_NET_IPv6
  669. case SIOCGLIFADDR: /* Get IP address */
  670. {
  671. dev = netdev_ifr_dev(req);
  672. if (dev)
  673. {
  674. FAR struct lifreq *lreq = (FAR struct lifreq *)req;
  675. ioctl_get_ipv6addr(&lreq->lifr_addr, dev->d_ipv6addr);
  676. ret = OK;
  677. }
  678. }
  679. break;
  680. #endif
  681. #ifdef CONFIG_NET_IPv6
  682. case SIOCSLIFADDR: /* Set IP address */
  683. {
  684. dev = netdev_ifr_dev(req);
  685. if (dev)
  686. {
  687. FAR struct lifreq *lreq = (FAR struct lifreq *)req;
  688. ioctl_set_ipv6addr(dev->d_ipv6addr, &lreq->lifr_addr);
  689. ret = OK;
  690. }
  691. }
  692. break;
  693. #endif
  694. #ifdef CONFIG_NET_IPv6
  695. case SIOCGLIFDSTADDR: /* Get P-to-P address */
  696. {
  697. dev = netdev_ifr_dev(req);
  698. if (dev)
  699. {
  700. FAR struct lifreq *lreq = (FAR struct lifreq *)req;
  701. ioctl_get_ipv6addr(&lreq->lifr_dstaddr, dev->d_ipv6draddr);
  702. ret = OK;
  703. }
  704. }
  705. break;
  706. #endif
  707. #ifdef CONFIG_NET_IPv6
  708. case SIOCSLIFDSTADDR: /* Set P-to-P address */
  709. {
  710. dev = netdev_ifr_dev(req);
  711. if (dev)
  712. {
  713. FAR struct lifreq *lreq = (FAR struct lifreq *)req;
  714. ioctl_set_ipv6addr(dev->d_ipv6draddr, &lreq->lifr_dstaddr);
  715. ret = OK;
  716. }
  717. }
  718. break;
  719. #endif
  720. #ifdef CONFIG_NET_IPv6
  721. case SIOCGLIFBRDADDR: /* Get broadcast IP address */
  722. case SIOCSLIFBRDADDR: /* Set broadcast IP address */
  723. {
  724. ret = -ENOSYS;
  725. }
  726. break;
  727. #endif
  728. #ifdef CONFIG_NET_IPv6
  729. case SIOCGLIFNETMASK: /* Get network mask */
  730. {
  731. dev = netdev_ifr_dev(req);
  732. if (dev)
  733. {
  734. FAR struct lifreq *lreq = (FAR struct lifreq *)req;
  735. ioctl_get_ipv6addr(&lreq->lifr_addr, dev->d_ipv6netmask);
  736. ret = OK;
  737. }
  738. }
  739. break;
  740. #endif
  741. #ifdef CONFIG_NET_IPv6
  742. case SIOCSLIFNETMASK: /* Set network mask */
  743. {
  744. dev = netdev_ifr_dev(req);
  745. if (dev)
  746. {
  747. FAR struct lifreq *lreq = (FAR struct lifreq *)req;
  748. ioctl_set_ipv6addr(dev->d_ipv6netmask, &lreq->lifr_addr);
  749. ret = OK;
  750. }
  751. }
  752. break;
  753. #endif
  754. case SIOCGLIFMTU: /* Get MTU size */
  755. case SIOCGIFMTU: /* Get MTU size */
  756. {
  757. dev = netdev_ifr_dev(req);
  758. if (dev)
  759. {
  760. req->ifr_mtu = NETDEV_PKTSIZE(dev);
  761. ret = OK;
  762. }
  763. }
  764. break;
  765. #ifdef CONFIG_NET_ICMPv6_AUTOCONF
  766. case SIOCIFAUTOCONF: /* Perform ICMPv6 auto-configuration */
  767. {
  768. dev = netdev_ifr_dev(req);
  769. if (dev)
  770. {
  771. ret = icmpv6_autoconfig(dev, psock);
  772. }
  773. }
  774. break;
  775. #endif
  776. case SIOCSIFFLAGS: /* Sets the interface flags */
  777. {
  778. /* Is this a request to bring the interface up? */
  779. dev = netdev_ifr_dev(req);
  780. if (dev)
  781. {
  782. if ((req->ifr_flags & IFF_UP) != 0)
  783. {
  784. /* Yes.. bring the interface up */
  785. netdev_ifup(dev);
  786. }
  787. /* Is this a request to take the interface down? */
  788. else if ((req->ifr_flags & IFF_DOWN) != 0)
  789. {
  790. /* Yes.. take the interface down */
  791. netdev_ifdown(dev);
  792. }
  793. }
  794. ret = OK;
  795. }
  796. break;
  797. case SIOCGIFFLAGS: /* Gets the interface flags */
  798. {
  799. dev = netdev_ifr_dev(req);
  800. if (dev)
  801. {
  802. req->ifr_flags = dev->d_flags;
  803. }
  804. ret = OK;
  805. }
  806. break;
  807. /* MAC address operations only make sense if Ethernet or 6LoWPAN are
  808. * supported.
  809. */
  810. #if defined(CONFIG_NET_ETHERNET) || defined(CONFIG_NET_6LOWPAN)
  811. case SIOCGIFHWADDR: /* Get hardware address */
  812. {
  813. dev = netdev_ifr_dev(req);
  814. if (dev)
  815. {
  816. #ifdef CONFIG_NET_ETHERNET
  817. if (dev->d_lltype == NET_LL_ETHERNET ||
  818. dev->d_lltype == NET_LL_IEEE80211)
  819. {
  820. req->ifr_hwaddr.sa_family = AF_INETX;
  821. memcpy(req->ifr_hwaddr.sa_data,
  822. dev->d_mac.ether.ether_addr_octet, IFHWADDRLEN);
  823. ret = OK;
  824. }
  825. else
  826. #endif
  827. #ifdef CONFIG_NET_6LOWPAN
  828. if (dev->d_lltype == NET_LL_IEEE802154 ||
  829. dev->d_lltype == NET_LL_PKTRADIO)
  830. {
  831. req->ifr_hwaddr.sa_family = AF_INETX;
  832. memcpy(req->ifr_hwaddr.sa_data,
  833. dev->d_mac.radio.nv_addr,
  834. dev->d_mac.radio.nv_addrlen);
  835. ret = OK;
  836. }
  837. else
  838. #endif
  839. {
  840. nerr("Unsupported link layer\n");
  841. }
  842. }
  843. }
  844. break;
  845. case SIOCSIFHWADDR: /* Set hardware address -- will not take effect until ifup */
  846. {
  847. dev = netdev_ifr_dev(req);
  848. if (dev)
  849. {
  850. #ifdef CONFIG_NET_ETHERNET
  851. if (dev->d_lltype == NET_LL_ETHERNET)
  852. {
  853. memcpy(dev->d_mac.ether.ether_addr_octet,
  854. req->ifr_hwaddr.sa_data, IFHWADDRLEN);
  855. ret = OK;
  856. }
  857. else
  858. #endif
  859. #ifdef CONFIG_NET_6LOWPAN
  860. if (dev->d_lltype == NET_LL_IEEE802154 ||
  861. dev->d_lltype == NET_LL_PKTRADIO)
  862. {
  863. FAR struct radio_driver_s *radio;
  864. struct radiodev_properties_s properties;
  865. /* Get the radio properties */
  866. radio = (FAR struct radio_driver_s *)dev;
  867. DEBUGASSERT(radio->r_properties != NULL);
  868. ret = radio->r_properties(radio, &properties);
  869. if (ret >= 0)
  870. {
  871. dev->d_mac.radio.nv_addrlen = properties.sp_addrlen;
  872. memcpy(dev->d_mac.radio.nv_addr,
  873. req->ifr_hwaddr.sa_data, NET_6LOWPAN_ADDRSIZE);
  874. }
  875. }
  876. else
  877. #endif
  878. {
  879. nerr("Unsupported link layer\n");
  880. }
  881. }
  882. }
  883. break;
  884. #endif
  885. case SIOCDIFADDR: /* Delete IP address */
  886. {
  887. dev = netdev_ifr_dev(req);
  888. if (dev)
  889. {
  890. #ifdef CONFIG_NET_IPv4
  891. dev->d_ipaddr = 0;
  892. #endif
  893. #ifdef CONFIG_NET_IPv6
  894. memset(&dev->d_ipv6addr, 0, sizeof(net_ipv6addr_t));
  895. #endif
  896. ret = OK;
  897. }
  898. }
  899. break;
  900. case SIOCGIFCOUNT: /* Get number of devices */
  901. {
  902. req->ifr_count = netdev_count();
  903. ret = -ENOSYS;
  904. }
  905. break;
  906. #ifdef CONFIG_NET_IPv4
  907. case SIOCGIFCONF: /* Return an interface list (IPv4) */
  908. {
  909. ret = netdev_ipv4_ifconf((FAR struct ifconf *)req);
  910. }
  911. break;
  912. #endif
  913. #ifdef CONFIG_NET_IPv6
  914. case SIOCGLIFCONF: /* Return an interface list (IPv6) */
  915. {
  916. ret = netdev_ipv6_ifconf((FAR struct lifconf *)req);
  917. }
  918. break;
  919. #endif
  920. #if defined(CONFIG_NETDEV_IOCTL) && defined(CONFIG_NETDEV_PHY_IOCTL)
  921. #ifdef CONFIG_ARCH_PHY_INTERRUPT
  922. case SIOCMIINOTIFY: /* Set up for PHY event notifications */
  923. {
  924. dev = netdev_ifr_dev(req);
  925. if (dev && dev->d_ioctl)
  926. {
  927. struct mii_ioctl_notify_s *notify = &req->ifr_ifru.ifru_mii_notify;
  928. ret = dev->d_ioctl(dev, cmd, ((unsigned long)(uintptr_t)notify));
  929. }
  930. }
  931. break;
  932. #endif
  933. case SIOCGMIIPHY: /* Get address of MII PHY in use */
  934. case SIOCGMIIREG: /* Get MII register via MDIO */
  935. case SIOCSMIIREG: /* Set MII register via MDIO */
  936. {
  937. dev = netdev_ifr_dev(req);
  938. if (dev && dev->d_ioctl)
  939. {
  940. struct mii_ioctl_data_s *mii_data = &req->ifr_ifru.ifru_mii_data;
  941. ret = dev->d_ioctl(dev, cmd, ((unsigned long)(uintptr_t)mii_data));
  942. }
  943. }
  944. break;
  945. #endif
  946. default:
  947. {
  948. ret = -ENOTTY;
  949. }
  950. break;
  951. }
  952. return ret;
  953. }
  954. /****************************************************************************
  955. * Name: netdev_imsfdev
  956. *
  957. * Description:
  958. * Verify the struct ip_msfilter and get the Ethernet device.
  959. *
  960. * Input Parameters:
  961. * req - The argument of the ioctl cmd
  962. *
  963. * Returned Value:
  964. * A pointer to the driver structure on success; NULL on failure.
  965. *
  966. ****************************************************************************/
  967. #ifdef CONFIG_NET_IGMP
  968. static FAR struct net_driver_s *netdev_imsfdev(FAR struct ip_msfilter *imsf)
  969. {
  970. if (imsf == NULL)
  971. {
  972. return NULL;
  973. }
  974. /* Find the network device associated with the address of the IP address
  975. * of the local device.
  976. */
  977. return netdev_findby_lipv4addr(imsf->imsf_interface.s_addr);
  978. }
  979. #endif
  980. /****************************************************************************
  981. * Name: netdev_imsf_ioctl
  982. *
  983. * Description:
  984. * Perform network device specific operations.
  985. *
  986. * Input Parameters:
  987. * psock Socket structure
  988. * dev Ethernet driver device structure
  989. * cmd The ioctl command
  990. * imsf The argument of the ioctl cmd
  991. *
  992. * Returned Value:
  993. * >=0 on success (positive non-zero values are cmd-specific)
  994. * Negated errno returned on failure.
  995. *
  996. ****************************************************************************/
  997. #ifdef CONFIG_NET_IGMP
  998. static int netdev_imsf_ioctl(FAR struct socket *psock, int cmd,
  999. FAR struct ip_msfilter *imsf)
  1000. {
  1001. FAR struct net_driver_s *dev;
  1002. int ret = -EINVAL;
  1003. ninfo("cmd: %d\n", cmd);
  1004. /* Execute the command */
  1005. switch (cmd)
  1006. {
  1007. case SIOCSIPMSFILTER: /* Set source filter content */
  1008. {
  1009. dev = netdev_imsfdev(imsf);
  1010. if (dev)
  1011. {
  1012. if (imsf->imsf_fmode == MCAST_INCLUDE)
  1013. {
  1014. ret = igmp_joingroup(dev, &imsf->imsf_multiaddr);
  1015. }
  1016. else
  1017. {
  1018. DEBUGASSERT(imsf->imsf_fmode == MCAST_EXCLUDE);
  1019. ret = igmp_leavegroup(dev, &imsf->imsf_multiaddr);
  1020. }
  1021. }
  1022. }
  1023. break;
  1024. case SIOCGIPMSFILTER: /* Retrieve source filter addresses */
  1025. default:
  1026. ret = -ENOTTY;
  1027. break;
  1028. }
  1029. return ret;
  1030. }
  1031. #endif
  1032. /****************************************************************************
  1033. * Name: netdev_arp_ioctl
  1034. *
  1035. * Description:
  1036. * Perform ARP table specific operations.
  1037. *
  1038. * Input Parameters:
  1039. * psock Socket structure
  1040. * dev Ethernet driver device structure
  1041. * cmd The ioctl command
  1042. * req The argument of the ioctl cmd
  1043. *
  1044. * Returned Value:
  1045. * >=0 on success (positive non-zero values are cmd-specific)
  1046. * Negated errno returned on failure.
  1047. *
  1048. ****************************************************************************/
  1049. #ifdef CONFIG_NET_ARP
  1050. static int netdev_arp_ioctl(FAR struct socket *psock, int cmd,
  1051. FAR struct arpreq *req)
  1052. {
  1053. int ret;
  1054. /* Execute the command */
  1055. switch (cmd)
  1056. {
  1057. case SIOCSARP: /* Set an ARP mapping */
  1058. {
  1059. if (req != NULL &&
  1060. req->arp_pa.sa_family == AF_INET &&
  1061. req->arp_ha.sa_family == ARPHRD_ETHER)
  1062. {
  1063. FAR struct sockaddr_in *addr =
  1064. (FAR struct sockaddr_in *)&req->arp_pa;
  1065. /* Update any existing ARP table entry for this protocol
  1066. * address -OR- add a new ARP table entry if there is not.
  1067. */
  1068. ret = arp_update(addr->sin_addr.s_addr,
  1069. (FAR uint8_t *)req->arp_ha.sa_data);
  1070. }
  1071. else
  1072. {
  1073. ret = -EINVAL;
  1074. }
  1075. }
  1076. break;
  1077. case SIOCDARP: /* Delete an ARP mapping */
  1078. {
  1079. if (req != NULL && req->arp_pa.sa_family == AF_INET)
  1080. {
  1081. FAR struct sockaddr_in *addr =
  1082. (FAR struct sockaddr_in *)&req->arp_pa;
  1083. /* Find the existing ARP table entry for this protocol address. */
  1084. FAR struct arp_entry_s *entry = arp_lookup(addr->sin_addr.s_addr);
  1085. if (entry != NULL)
  1086. {
  1087. /* The ARP table is fixed size; an entry is deleted
  1088. * by nullifying its protocol address.
  1089. */
  1090. entry->at_ipaddr = 0;
  1091. ret = OK;
  1092. }
  1093. else
  1094. {
  1095. ret = -ENOENT;
  1096. }
  1097. }
  1098. else
  1099. {
  1100. ret = -EINVAL;
  1101. }
  1102. }
  1103. break;
  1104. case SIOCGARP: /* Get an ARP mapping */
  1105. {
  1106. if (req != NULL && req->arp_pa.sa_family == AF_INET)
  1107. {
  1108. FAR struct sockaddr_in *addr =
  1109. (FAR struct sockaddr_in *)&req->arp_pa;
  1110. /* Get the hardware address from an existing ARP table entry
  1111. * matching this protocol address.
  1112. */
  1113. ret = arp_find(addr->sin_addr.s_addr,
  1114. (FAR struct ether_addr *)req->arp_ha.sa_data);
  1115. if (ret >= 0)
  1116. {
  1117. /* Return the mapped hardware address. */
  1118. req->arp_ha.sa_family = ARPHRD_ETHER;
  1119. ret = OK;
  1120. }
  1121. }
  1122. else
  1123. {
  1124. ret = -EINVAL;
  1125. }
  1126. }
  1127. break;
  1128. default:
  1129. ret = -ENOTTY;
  1130. break;
  1131. }
  1132. return ret;
  1133. }
  1134. #endif
  1135. /****************************************************************************
  1136. * Name: netdev_rt_ioctl
  1137. *
  1138. * Description:
  1139. * Perform routing table specific operations.
  1140. *
  1141. * Input Parameters:
  1142. * psock Socket structure
  1143. * dev Ethernet driver device structure
  1144. * cmd The ioctl command
  1145. * rtentry The argument of the ioctl cmd
  1146. *
  1147. * Returned Value:
  1148. * >=0 on success (positive non-zero values are cmd-specific)
  1149. * Negated errno returned on failure.
  1150. *
  1151. ****************************************************************************/
  1152. #ifdef CONFIG_NET_ROUTE
  1153. static int netdev_rt_ioctl(FAR struct socket *psock, int cmd,
  1154. FAR struct rtentry *rtentry)
  1155. {
  1156. int ret = -EAFNOSUPPORT;
  1157. /* Execute the command */
  1158. switch (cmd)
  1159. {
  1160. case SIOCADDRT: /* Add an entry to the routing table */
  1161. {
  1162. /* The target address and the netmask are required values */
  1163. if (!rtentry || !rtentry->rt_target || !rtentry->rt_netmask)
  1164. {
  1165. return -EINVAL;
  1166. }
  1167. #ifdef CONFIG_NET_IPv4
  1168. #ifdef CONFIG_NET_IPv6
  1169. if (rtentry->rt_target->ss_family == AF_INET)
  1170. #endif
  1171. {
  1172. #ifdef HAVE_WRITABLE_IPv4ROUTE
  1173. ret = ioctl_add_ipv4route(rtentry);
  1174. #else
  1175. ret = -EACCES;
  1176. #endif
  1177. }
  1178. #endif /* CONFIG_NET_IPv4 */
  1179. #ifdef CONFIG_NET_IPv6
  1180. #ifdef CONFIG_NET_IPv4
  1181. else
  1182. #endif
  1183. {
  1184. #ifdef HAVE_WRITABLE_IPv6ROUTE
  1185. ret = ioctl_add_ipv6route(rtentry);
  1186. #else
  1187. ret = -EACCES;
  1188. #endif
  1189. }
  1190. #endif /* CONFIG_NET_IPv6 */
  1191. }
  1192. break;
  1193. case SIOCDELRT: /* Delete an entry from the routing table */
  1194. {
  1195. /* The target address and the netmask are required values */
  1196. if (!rtentry || !rtentry->rt_target || !rtentry->rt_netmask)
  1197. {
  1198. return -EINVAL;
  1199. }
  1200. #ifdef CONFIG_NET_IPv4
  1201. #ifdef CONFIG_NET_IPv6
  1202. if (rtentry->rt_target->ss_family == AF_INET)
  1203. #endif
  1204. {
  1205. #ifdef HAVE_WRITABLE_IPv4ROUTE
  1206. ret = ioctl_del_ipv4route(rtentry);
  1207. #else
  1208. ret = -EACCES;
  1209. #endif
  1210. }
  1211. #endif /* CONFIG_NET_IPv4 */
  1212. #ifdef CONFIG_NET_IPv6
  1213. #ifdef CONFIG_NET_IPv4
  1214. else
  1215. #endif
  1216. {
  1217. #ifdef HAVE_WRITABLE_IPv6ROUTE
  1218. ret = ioctl_del_ipv6route(rtentry);
  1219. #else
  1220. ret = -EACCES;
  1221. #endif
  1222. }
  1223. #endif /* CONFIG_NET_IPv6 */
  1224. }
  1225. break;
  1226. default:
  1227. ret = -ENOTTY;
  1228. break;
  1229. }
  1230. return ret;
  1231. }
  1232. #endif
  1233. /****************************************************************************
  1234. * Name: netdev_usrsock_ioctl
  1235. *
  1236. * Description:
  1237. * Perform user private ioctl operations.
  1238. *
  1239. * Parameters:
  1240. * psock Socket structure
  1241. * cmd The ioctl command
  1242. * arg The argument of the ioctl cmd
  1243. *
  1244. * Return:
  1245. * >=0 on success (positive non-zero values are cmd-specific)
  1246. * Negated errno returned on failure.
  1247. *
  1248. ****************************************************************************/
  1249. #ifdef CONFIG_NET_USRSOCK
  1250. static int netdev_usrsock_ioctl(FAR struct socket *psock, int cmd,
  1251. unsigned long arg)
  1252. {
  1253. if (psock->s_sockif && psock->s_sockif->si_ioctl)
  1254. {
  1255. ssize_t arglen;
  1256. arglen = net_ioctl_arglen(cmd);
  1257. if (arglen < 0)
  1258. {
  1259. return arglen;
  1260. }
  1261. return psock->s_sockif->si_ioctl(psock, cmd, (FAR void *)arg, arglen);
  1262. }
  1263. else
  1264. {
  1265. return -ENOTTY;
  1266. }
  1267. }
  1268. #endif
  1269. /****************************************************************************
  1270. * Public Functions
  1271. ****************************************************************************/
  1272. /****************************************************************************
  1273. * Name: net_ioctl_arglen
  1274. *
  1275. * Description:
  1276. * Calculate the ioctl argument buffer length.
  1277. *
  1278. * Input Parameters:
  1279. *
  1280. * cmd The ioctl command
  1281. *
  1282. * Returned Value:
  1283. * The argument buffer length, or error code.
  1284. *
  1285. ****************************************************************************/
  1286. #ifdef CONFIG_NET_USRSOCK
  1287. ssize_t net_ioctl_arglen(int cmd)
  1288. {
  1289. switch (cmd)
  1290. {
  1291. case SIOCGIFADDR:
  1292. case SIOCSIFADDR:
  1293. case SIOCGIFDSTADDR:
  1294. case SIOCSIFDSTADDR:
  1295. case SIOCGIFBRDADDR:
  1296. case SIOCSIFBRDADDR:
  1297. case SIOCGIFNETMASK:
  1298. case SIOCSIFNETMASK:
  1299. case SIOCGIFMTU:
  1300. case SIOCGIFHWADDR:
  1301. case SIOCSIFHWADDR:
  1302. case SIOCDIFADDR:
  1303. case SIOCGIFCOUNT:
  1304. case SIOCSIFFLAGS:
  1305. case SIOCGIFFLAGS:
  1306. return sizeof(struct ifreq);
  1307. case SIOCGLIFADDR:
  1308. case SIOCSLIFADDR:
  1309. case SIOCGLIFDSTADDR:
  1310. case SIOCSLIFDSTADDR:
  1311. case SIOCGLIFBRDADDR:
  1312. case SIOCSLIFBRDADDR:
  1313. case SIOCGLIFNETMASK:
  1314. case SIOCSLIFNETMASK:
  1315. case SIOCGLIFMTU:
  1316. case SIOCIFAUTOCONF:
  1317. return sizeof(struct lifreq);
  1318. case SIOCGIFCONF:
  1319. return sizeof(struct ifconf);
  1320. case SIOCGLIFCONF:
  1321. return sizeof(struct lifconf);
  1322. case SIOCGIPMSFILTER:
  1323. case SIOCSIPMSFILTER:
  1324. return sizeof(struct ip_msfilter);
  1325. case SIOCSARP:
  1326. case SIOCDARP:
  1327. case SIOCGARP:
  1328. return sizeof(struct arpreq);
  1329. case SIOCADDRT:
  1330. case SIOCDELRT:
  1331. return sizeof(struct rtentry);
  1332. case SIOCMIINOTIFY:
  1333. return sizeof(struct mii_ioctl_notify_s);
  1334. case SIOCGMIIPHY:
  1335. case SIOCGMIIREG:
  1336. case SIOCSMIIREG:
  1337. return sizeof(struct mii_ioctl_data_s);
  1338. default:
  1339. #ifdef CONFIG_NETDEV_IOCTL
  1340. # ifdef CONFIG_NETDEV_WIRELESS_IOCTL
  1341. if (_WLIOCVALID(cmd) && _IOC_NR(cmd) <= WL_NNETCMDS)
  1342. {
  1343. return sizeof(struct iwreq);
  1344. }
  1345. # endif
  1346. # ifdef CONFIG_WIRELESS_IEEE802154
  1347. if (_MAC802154IOCVALID(cmd))
  1348. {
  1349. return sizeof(struct ieee802154_netmac_s);
  1350. }
  1351. # endif
  1352. # ifdef CONFIG_WIRELESS_PKTRADIO
  1353. if (WL_ISPKTRADIOCMD(cmd))
  1354. {
  1355. return sizeof(struct pktradio_ifreq_s);
  1356. }
  1357. # endif
  1358. # ifdef CONFIG_WIRELESS_BLUETOOTH
  1359. if (WL_IBLUETOOTHCMD(cmd))
  1360. {
  1361. return sizeof(struct btreq_s);
  1362. }
  1363. # endif
  1364. #endif
  1365. return -ENOTTY;
  1366. }
  1367. }
  1368. #endif
  1369. /****************************************************************************
  1370. * Name: psock_ioctl
  1371. *
  1372. * Description:
  1373. * Perform network device specific operations.
  1374. *
  1375. * Input Parameters:
  1376. * psock A pointer to a NuttX-specific, internal socket structure
  1377. * cmd The ioctl command
  1378. * arg The argument of the ioctl cmd
  1379. *
  1380. * Returned Value:
  1381. * A non-negative value is returned on success; a negated errno value is
  1382. * returned on any failure to indicate the nature of the failure:
  1383. *
  1384. * EBADF
  1385. * 'psock' is not a valid, connected socket structure.
  1386. * EFAULT
  1387. * 'arg' references an inaccessible memory area.
  1388. * ENOTTY
  1389. * 'cmd' not valid.
  1390. * EINVAL
  1391. * 'arg' is not valid.
  1392. * ENOTTY
  1393. * 'sockfd' is not associated with a network device.
  1394. * ENOTTY
  1395. * The specified request does not apply to the kind of object that the
  1396. * descriptor 'sockfd' references.
  1397. *
  1398. ****************************************************************************/
  1399. int psock_ioctl(FAR struct socket *psock, int cmd, unsigned long arg)
  1400. {
  1401. int ret;
  1402. /* Verify that the psock corresponds to valid, allocated socket */
  1403. if (psock == NULL || psock->s_crefs <= 0)
  1404. {
  1405. return -EBADF;
  1406. }
  1407. /* Execute the command. First check for a standard network IOCTL command. */
  1408. #ifdef CONFIG_NET_USRSOCK
  1409. /* Check for a USRSOCK ioctl command */
  1410. ret = netdev_usrsock_ioctl(psock, cmd, arg);
  1411. if (ret == -ENOTTY)
  1412. #endif
  1413. {
  1414. /* Check for a standard network IOCTL command. */
  1415. ret = netdev_ifr_ioctl(psock, cmd, (FAR struct ifreq *)((uintptr_t)arg));
  1416. }
  1417. #if defined(CONFIG_NETDEV_IOCTL) && defined(CONFIG_NETDEV_WIRELESS_IOCTL)
  1418. /* Check for a wireless network command */
  1419. if (ret == -ENOTTY)
  1420. {
  1421. FAR struct iwreq *wifrreq;
  1422. wifrreq = (FAR struct iwreq *)((uintptr_t)arg);
  1423. ret = netdev_wifr_ioctl(psock, cmd, wifrreq);
  1424. }
  1425. #endif
  1426. #ifdef HAVE_IEEE802154_IOCTL
  1427. /* Check for a IEEE802.15.4 network device IOCTL command */
  1428. if (ret == -ENOTTY)
  1429. {
  1430. ret = netdev_iee802154_ioctl(psock, cmd, arg);
  1431. }
  1432. #endif
  1433. #ifdef HAVE_PKTRADIO_IOCTL
  1434. /* Check for a non-IEEE802.15.4 packet radio network device IOCTL command */
  1435. if (ret == -ENOTTY)
  1436. {
  1437. ret = netdev_pktradio_ioctl(psock, cmd, arg);
  1438. }
  1439. #endif
  1440. #ifdef HAVE_BLUETOOTH_IOCTL
  1441. /* Check for Bluetooth network device IOCTL command */
  1442. if (ret == -ENOTTY)
  1443. {
  1444. ret = netdev_bluetooth_ioctl(psock, cmd, arg);
  1445. }
  1446. #endif
  1447. #ifdef CONFIG_NET_IGMP
  1448. /* Check for address filtering commands */
  1449. if (ret == -ENOTTY)
  1450. {
  1451. ret = netdev_imsf_ioctl(psock, cmd,
  1452. (FAR struct ip_msfilter *)((uintptr_t)arg));
  1453. }
  1454. #endif
  1455. #ifdef CONFIG_NET_ARP
  1456. /* Check for ARP table IOCTL commands */
  1457. if (ret == -ENOTTY)
  1458. {
  1459. ret = netdev_arp_ioctl(psock, cmd,
  1460. (FAR struct arpreq *)((uintptr_t)arg));
  1461. }
  1462. #endif
  1463. #ifdef CONFIG_NET_ROUTE
  1464. /* Check for Routing table IOCTL commands */
  1465. if (ret == -ENOTTY)
  1466. {
  1467. ret = netdev_rt_ioctl(psock, cmd,
  1468. (FAR struct rtentry *)((uintptr_t)arg));
  1469. }
  1470. #endif
  1471. return ret;
  1472. }
  1473. /****************************************************************************
  1474. * Name: netdev_ioctl
  1475. *
  1476. * Description:
  1477. * Perform network device specific operations.
  1478. *
  1479. * Input Parameters:
  1480. * sockfd Socket descriptor of device
  1481. * cmd The ioctl command
  1482. * arg The argument of the ioctl cmd
  1483. *
  1484. * Returned Value:
  1485. * A non-negative value is returned on success; a negated errno value is
  1486. * returned on any failure to indicate the nature of the failure:
  1487. *
  1488. * EBADF
  1489. * 'sockfd' is not a valid socket descriptor.
  1490. * EFAULT
  1491. * 'arg' references an inaccessible memory area.
  1492. * ENOTTY
  1493. * 'cmd' not valid.
  1494. * EINVAL
  1495. * 'arg' is not valid.
  1496. * ENOTTY
  1497. * 'sockfd' is not associated with a network device.
  1498. * ENOTTY
  1499. * The specified request does not apply to the kind of object that the
  1500. * descriptor 'sockfd' references.
  1501. *
  1502. ****************************************************************************/
  1503. int netdev_ioctl(int sockfd, int cmd, unsigned long arg)
  1504. {
  1505. FAR struct socket *psock = sockfd_socket(sockfd);
  1506. return psock_ioctl(psock, cmd, arg);
  1507. }
  1508. /****************************************************************************
  1509. * Name: netdev_ifup / netdev_ifdown
  1510. *
  1511. * Description:
  1512. * Bring the interface up/down
  1513. *
  1514. ****************************************************************************/
  1515. void netdev_ifup(FAR struct net_driver_s *dev)
  1516. {
  1517. /* Make sure that the device supports the d_ifup() method */
  1518. if (dev->d_ifup != NULL)
  1519. {
  1520. /* Is the interface already up? */
  1521. if ((dev->d_flags & IFF_UP) == 0)
  1522. {
  1523. /* No, bring the interface up now */
  1524. if (dev->d_ifup(dev) == OK)
  1525. {
  1526. /* Mark the interface as up */
  1527. dev->d_flags |= IFF_UP;
  1528. }
  1529. }
  1530. }
  1531. }
  1532. void netdev_ifdown(FAR struct net_driver_s *dev)
  1533. {
  1534. /* Check sure that the device supports the d_ifdown() method */
  1535. if (dev->d_ifdown != NULL)
  1536. {
  1537. /* Is the interface already down? */
  1538. if ((dev->d_flags & IFF_UP) != 0)
  1539. {
  1540. /* No, take the interface down now */
  1541. if (dev->d_ifdown(dev) == OK)
  1542. {
  1543. /* Mark the interface as down */
  1544. dev->d_flags &= ~IFF_UP;
  1545. }
  1546. }
  1547. /* Notify clients that the network has been taken down */
  1548. (void)devif_dev_event(dev, NULL, NETDEV_DOWN);
  1549. #ifdef CONFIG_NETDOWN_NOTIFIER
  1550. /* Provide signal notifications to threads that want to be
  1551. * notified of the network down state via signal.
  1552. */
  1553. netdown_notifier_signal(dev);
  1554. #endif
  1555. }
  1556. }