vlan_ioctl.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. /*
  2. * hostapd / VLAN ioctl API
  3. * Copyright 2003, Instant802 Networks, Inc.
  4. * Copyright 2005-2006, Devicescape Software, Inc.
  5. * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
  6. *
  7. * This software may be distributed under the terms of the BSD license.
  8. * See README for more details.
  9. */
  10. #include "utils/includes.h"
  11. #include <sys/ioctl.h>
  12. #include "utils/common.h"
  13. #include "common/linux_vlan.h"
  14. #include "vlan_util.h"
  15. int vlan_rem(const char *if_name)
  16. {
  17. int fd;
  18. struct vlan_ioctl_args if_request;
  19. wpa_printf(MSG_DEBUG, "VLAN: vlan_rem(%s)", if_name);
  20. if ((os_strlen(if_name) + 1) > sizeof(if_request.device1)) {
  21. wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'",
  22. if_name);
  23. return -1;
  24. }
  25. if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  26. wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
  27. "failed: %s", __func__, strerror(errno));
  28. return -1;
  29. }
  30. os_memset(&if_request, 0, sizeof(if_request));
  31. os_strlcpy(if_request.device1, if_name, sizeof(if_request.device1));
  32. if_request.cmd = DEL_VLAN_CMD;
  33. if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) {
  34. wpa_printf(MSG_ERROR, "VLAN: %s: DEL_VLAN_CMD failed for %s: "
  35. "%s", __func__, if_name, strerror(errno));
  36. close(fd);
  37. return -1;
  38. }
  39. close(fd);
  40. return 0;
  41. }
  42. /*
  43. Add a vlan interface with VLAN ID 'vid' and tagged interface
  44. 'if_name'.
  45. returns -1 on error
  46. returns 1 if the interface already exists
  47. returns 0 otherwise
  48. */
  49. int vlan_add(const char *if_name, int vid, const char *vlan_if_name)
  50. {
  51. int fd;
  52. struct vlan_ioctl_args if_request;
  53. wpa_printf(MSG_DEBUG, "VLAN: vlan_add(if_name=%s, vid=%d)",
  54. if_name, vid);
  55. ifconfig_up(if_name);
  56. if ((os_strlen(if_name) + 1) > sizeof(if_request.device1)) {
  57. wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'",
  58. if_name);
  59. return -1;
  60. }
  61. if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  62. wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
  63. "failed: %s", __func__, strerror(errno));
  64. return -1;
  65. }
  66. os_memset(&if_request, 0, sizeof(if_request));
  67. /* Determine if a suitable vlan device already exists. */
  68. os_snprintf(if_request.device1, sizeof(if_request.device1), "vlan%d",
  69. vid);
  70. if_request.cmd = GET_VLAN_VID_CMD;
  71. if (ioctl(fd, SIOCSIFVLAN, &if_request) == 0 &&
  72. if_request.u.VID == vid) {
  73. if_request.cmd = GET_VLAN_REALDEV_NAME_CMD;
  74. if (ioctl(fd, SIOCSIFVLAN, &if_request) == 0 &&
  75. os_strncmp(if_request.u.device2, if_name,
  76. sizeof(if_request.u.device2)) == 0) {
  77. close(fd);
  78. wpa_printf(MSG_DEBUG,
  79. "VLAN: vlan_add: if_name %s exists already",
  80. if_request.device1);
  81. return 1;
  82. }
  83. }
  84. /* A suitable vlan device does not already exist, add one. */
  85. os_memset(&if_request, 0, sizeof(if_request));
  86. os_strlcpy(if_request.device1, if_name, sizeof(if_request.device1));
  87. if_request.u.VID = vid;
  88. if_request.cmd = ADD_VLAN_CMD;
  89. if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) {
  90. wpa_printf(MSG_ERROR,
  91. "VLAN: %s: ADD_VLAN_CMD failed for %s: %s",
  92. __func__, if_request.device1, strerror(errno));
  93. close(fd);
  94. return -1;
  95. }
  96. close(fd);
  97. return 0;
  98. }
  99. int vlan_set_name_type(unsigned int name_type)
  100. {
  101. int fd;
  102. struct vlan_ioctl_args if_request;
  103. wpa_printf(MSG_DEBUG, "VLAN: vlan_set_name_type(name_type=%u)",
  104. name_type);
  105. if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  106. wpa_printf(MSG_ERROR,
  107. "VLAN: %s: socket(AF_INET,SOCK_STREAM) failed: %s",
  108. __func__, strerror(errno));
  109. return -1;
  110. }
  111. os_memset(&if_request, 0, sizeof(if_request));
  112. if_request.u.name_type = name_type;
  113. if_request.cmd = SET_VLAN_NAME_TYPE_CMD;
  114. if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) {
  115. wpa_printf(MSG_ERROR,
  116. "VLAN: %s: SET_VLAN_NAME_TYPE_CMD name_type=%u failed: %s",
  117. __func__, name_type, strerror(errno));
  118. close(fd);
  119. return -1;
  120. }
  121. close(fd);
  122. return 0;
  123. }