linux_ioctl.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. /*
  2. * Linux ioctl helper functions for driver wrappers
  3. * Copyright (c) 2002-2010, Jouni Malinen <j@w1.fi>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. *
  9. * Alternatively, this software may be distributed under the terms of BSD
  10. * license.
  11. *
  12. * See README and COPYING for more details.
  13. */
  14. #include "utils/includes.h"
  15. #include <sys/ioctl.h>
  16. #include <net/if.h>
  17. #include <net/if_arp.h>
  18. #include "utils/common.h"
  19. #include "linux_ioctl.h"
  20. int linux_set_iface_flags(int sock, const char *ifname, int dev_up)
  21. {
  22. struct ifreq ifr;
  23. if (sock < 0)
  24. return -1;
  25. os_memset(&ifr, 0, sizeof(ifr));
  26. os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
  27. if (ioctl(sock, SIOCGIFFLAGS, &ifr) != 0) {
  28. wpa_printf(MSG_ERROR, "Could not read interface %s flags: %s",
  29. ifname, strerror(errno));
  30. return -1;
  31. }
  32. if (dev_up) {
  33. if (ifr.ifr_flags & IFF_UP)
  34. return 0;
  35. ifr.ifr_flags |= IFF_UP;
  36. } else {
  37. if (!(ifr.ifr_flags & IFF_UP))
  38. return 0;
  39. ifr.ifr_flags &= ~IFF_UP;
  40. }
  41. if (ioctl(sock, SIOCSIFFLAGS, &ifr) != 0) {
  42. wpa_printf(MSG_ERROR, "Could not set interface %s flags: %s",
  43. ifname, strerror(errno));
  44. return -1;
  45. }
  46. return 0;
  47. }
  48. int linux_get_ifhwaddr(int sock, const char *ifname, u8 *addr)
  49. {
  50. struct ifreq ifr;
  51. os_memset(&ifr, 0, sizeof(ifr));
  52. os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
  53. if (ioctl(sock, SIOCGIFHWADDR, &ifr)) {
  54. wpa_printf(MSG_ERROR, "Could not get interface %s hwaddr: %s",
  55. ifname, strerror(errno));
  56. return -1;
  57. }
  58. if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) {
  59. wpa_printf(MSG_ERROR, "%s: Invalid HW-addr family 0x%04x",
  60. ifname, ifr.ifr_hwaddr.sa_family);
  61. return -1;
  62. }
  63. os_memcpy(addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
  64. return 0;
  65. }
  66. int linux_set_ifhwaddr(int sock, const char *ifname, const u8 *addr)
  67. {
  68. struct ifreq ifr;
  69. os_memset(&ifr, 0, sizeof(ifr));
  70. os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
  71. os_memcpy(ifr.ifr_hwaddr.sa_data, addr, ETH_ALEN);
  72. ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
  73. if (ioctl(sock, SIOCSIFHWADDR, &ifr)) {
  74. wpa_printf(MSG_DEBUG, "Could not set interface %s hwaddr: %s",
  75. ifname, strerror(errno));
  76. return -1;
  77. }
  78. return 0;
  79. }
  80. #ifndef SIOCBRADDBR
  81. #define SIOCBRADDBR 0x89a0
  82. #endif
  83. #ifndef SIOCBRDELBR
  84. #define SIOCBRDELBR 0x89a1
  85. #endif
  86. #ifndef SIOCBRADDIF
  87. #define SIOCBRADDIF 0x89a2
  88. #endif
  89. #ifndef SIOCBRDELIF
  90. #define SIOCBRDELIF 0x89a3
  91. #endif
  92. int linux_br_add(int sock, const char *brname)
  93. {
  94. if (ioctl(sock, SIOCBRADDBR, brname) < 0) {
  95. wpa_printf(MSG_DEBUG, "Could not add bridge %s: %s",
  96. brname, strerror(errno));
  97. return -1;
  98. }
  99. return 0;
  100. }
  101. int linux_br_del(int sock, const char *brname)
  102. {
  103. if (ioctl(sock, SIOCBRDELBR, brname) < 0) {
  104. wpa_printf(MSG_DEBUG, "Could not remove bridge %s: %s",
  105. brname, strerror(errno));
  106. return -1;
  107. }
  108. return 0;
  109. }
  110. int linux_br_add_if(int sock, const char *brname, const char *ifname)
  111. {
  112. struct ifreq ifr;
  113. int ifindex;
  114. ifindex = if_nametoindex(ifname);
  115. if (ifindex == 0)
  116. return -1;
  117. os_memset(&ifr, 0, sizeof(ifr));
  118. os_strlcpy(ifr.ifr_name, brname, IFNAMSIZ);
  119. ifr.ifr_ifindex = ifindex;
  120. if (ioctl(sock, SIOCBRADDIF, &ifr) < 0) {
  121. wpa_printf(MSG_DEBUG, "Could not add interface %s into bridge "
  122. "%s: %s", ifname, brname, strerror(errno));
  123. return -1;
  124. }
  125. return 0;
  126. }
  127. int linux_br_del_if(int sock, const char *brname, const char *ifname)
  128. {
  129. struct ifreq ifr;
  130. int ifindex;
  131. ifindex = if_nametoindex(ifname);
  132. if (ifindex == 0)
  133. return -1;
  134. os_memset(&ifr, 0, sizeof(ifr));
  135. os_strlcpy(ifr.ifr_name, brname, IFNAMSIZ);
  136. ifr.ifr_ifindex = ifindex;
  137. if (ioctl(sock, SIOCBRDELIF, &ifr) < 0) {
  138. wpa_printf(MSG_DEBUG, "Could not remove interface %s from "
  139. "bridge %s: %s", ifname, brname, strerror(errno));
  140. return -1;
  141. }
  142. return 0;
  143. }
  144. int linux_br_get(char *brname, const char *ifname)
  145. {
  146. char path[128], brlink[128], *pos;
  147. os_snprintf(path, sizeof(path), "/sys/class/net/%s/brport/bridge",
  148. ifname);
  149. os_memset(brlink, 0, sizeof(brlink));
  150. if (readlink(path, brlink, sizeof(brlink) - 1) < 0)
  151. return -1;
  152. pos = os_strrchr(brlink, '/');
  153. if (pos == NULL)
  154. return -1;
  155. pos++;
  156. os_strlcpy(brname, pos, IFNAMSIZ);
  157. return 0;
  158. }