NetPlatform_sunos.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. /* vim: set expandtab ts=4 sw=4: */
  2. /*
  3. * You may redistribute this program and/or modify it under the terms of
  4. * the GNU General Public License as published by the Free Software Foundation,
  5. * either version 3 of the License, or (at your option) any later version.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. * You should have received a copy of the GNU General Public License
  13. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. #include "util/platform/netdev/NetPlatform.h"
  16. #include "util/Assert.h"
  17. #include "util/platform/Sockaddr.h"
  18. #include <errno.h>
  19. #include <stdio.h>
  20. #include <sys/ioctl.h>
  21. #include <unistd.h>
  22. #include <string.h>
  23. #include <sys/socket.h>
  24. #include <sys/types.h>
  25. #include <stdlib.h>
  26. #include <stddef.h>
  27. #include <net/if.h>
  28. #include <ctype.h>
  29. #include <sys/stropts.h>
  30. #include <sys/sockio.h>
  31. #include <fcntl.h>
  32. #include <net/route.h>
  33. static void maskForPrefix(uint8_t mask[16], int prefix)
  34. {
  35. for (int i = 0; i < 16; i += 8) {
  36. if (i + 8 <= prefix) {
  37. mask[i] = 0xff;
  38. } else if (i > prefix) {
  39. mask[i] = 0x00;
  40. } else {
  41. mask[i] = (0xff << (i + 8 - prefix)) & 0xff;
  42. }
  43. }
  44. }
  45. struct RouteMessage {
  46. struct rt_msghdr header;
  47. struct sockaddr_in6 dest;
  48. struct sockaddr_in6 gateway;
  49. struct sockaddr_in6 netmask;
  50. };
  51. Assert_compileTime(sizeof(struct RouteMessage) == 172);
  52. static void setupRoute(const uint8_t address[16],
  53. int prefixLen,
  54. struct Log* logger,
  55. struct Except* eh)
  56. {
  57. struct RouteMessage rm = {
  58. .header = {
  59. .rtm_type = RTM_ADD,
  60. .rtm_version = RTM_VERSION,
  61. .rtm_seq = 0,
  62. .rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK,
  63. .rtm_msglen = sizeof(struct RouteMessage)
  64. },
  65. .dest = {
  66. .sin6_family = AF_INET6
  67. },
  68. .gateway = {
  69. .sin6_family = AF_INET6
  70. },
  71. .netmask = {
  72. .sin6_family = AF_INET6
  73. }
  74. };
  75. memcpy(&rm.dest.sin6_addr, address, 16);
  76. memcpy(&rm.gateway.sin6_addr, address, 16);
  77. maskForPrefix((uint8_t*) &rm.netmask.sin6_addr, prefixLen);
  78. int sock = socket(PF_ROUTE, SOCK_RAW, 0);
  79. if (sock == -1) {
  80. Except_throw(eh, "open route socket [%s]", strerror(errno));
  81. }
  82. ssize_t returnLen = write(sock, (char*) &rm, rm.header.rtm_msglen);
  83. if (returnLen < 0) {
  84. Except_throw(eh, "insert route [%s]", strerror(errno));
  85. } else if (returnLen < rm.header.rtm_msglen) {
  86. Except_throw(eh,
  87. "insert route returned only [%d] of [%d]",
  88. (int)returnLen, rm.header.rtm_msglen);
  89. }
  90. }
  91. static void addIp4Address(const char* interfaceName,
  92. const uint8_t address[4],
  93. int prefixLen,
  94. struct Log* logger,
  95. struct Except* eh)
  96. {
  97. // TODO(cjd): implement this and then remove the exception from TUNInterface_ipv4_root_test.c
  98. Except_throw(eh, "unimplemented");
  99. }
  100. static void addIp6Address(const char* interfaceName,
  101. const uint8_t address[16],
  102. int prefixLen,
  103. struct Log* logger,
  104. struct Except* eh)
  105. {
  106. struct lifreq ifr = {
  107. .lifr_ppa = 0,
  108. .lifr_flags = 0
  109. };
  110. char* error = NULL;
  111. struct sockaddr_in6* sin6 = (struct sockaddr_in6 *) &ifr.lifr_addr;
  112. maskForPrefix((uint8_t*) sin6->sin6_addr.s6_addr, prefixLen);
  113. ifr.lifr_addr.ss_family = AF_INET6;
  114. strncpy(ifr.lifr_name, interfaceName, LIFNAMSIZ);
  115. int udpSock = socket(AF_INET6, SOCK_DGRAM, 0);
  116. if (udpSock < 0) {
  117. error = "socket(AF_INET6, SOCK_DGRAM, 0)";
  118. } else if (ioctl(udpSock, SIOCSLIFNETMASK, (caddr_t)&ifr) < 0) {
  119. // set the netmask.
  120. error = "ioctl(SIOCSLIFNETMASK) (setting netmask)";
  121. }
  122. memcpy(&sin6->sin6_addr, address, 16);
  123. if (!error && ioctl(udpSock, SIOCSLIFADDR, (caddr_t)&ifr) < 0) {
  124. // set the ip address.
  125. error = "ioctl(SIOCSLIFADDR) (setting ipv6 address)";
  126. }
  127. if (!error && ioctl(udpSock, SIOCSLIFDSTADDR, (caddr_t)&ifr) < 0) {
  128. // set the destination address for the point-to-point connection
  129. // use the same as the source address since we're not really using it.
  130. error = "ioctl(SIOCGLIFDSTADDR) (setting point-to-point destination address)";
  131. }
  132. memset(sin6, 0, sizeof(struct sockaddr_in6));
  133. if (!error && ioctl(udpSock, SIOCGLIFFLAGS, (caddr_t)&ifr) < 0) {
  134. // get the flags for the device.
  135. error = "ioctl(SIOCGLIFFLAGS) (getting device flags)";
  136. }
  137. ifr.lifr_flags |= IFF_UP;
  138. if (!error && ioctl(udpSock, SIOCSLIFFLAGS, (caddr_t)&ifr) < 0) {
  139. // bring the interface up
  140. error = "ioctl(SIOCSLIFFLAGS) (bringing the interface up)";
  141. }
  142. if (error) {
  143. int err = errno;
  144. close(udpSock);
  145. Except_throw(eh, "%s [%s]",
  146. error, strerror(err));
  147. }
  148. close(udpSock);
  149. setupRoute(address, prefixLen, logger, eh);
  150. }
  151. void NetPlatform_addAddress(const char* interfaceName,
  152. const uint8_t* address,
  153. int prefixLen,
  154. int addrFam,
  155. struct Log* logger,
  156. struct Except* eh)
  157. {
  158. if (addrFam == Sockaddr_AF_INET6) {
  159. addIp6Address(interfaceName, address, prefixLen, logger, eh);
  160. } else if (addrFam == Sockaddr_AF_INET) {
  161. addIp4Address(interfaceName, address, prefixLen, logger, eh);
  162. } else {
  163. Assert_true(0);
  164. }
  165. }
  166. void NetPlatform_setMTU(const char* interfaceName,
  167. uint32_t mtu,
  168. struct Log* logger,
  169. struct Except* eh)
  170. {
  171. Except_throw(eh, "Not implemented in Illumos");
  172. }