NetPlatform_sunos.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  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 "util/Bits.h"
  19. #include <errno.h>
  20. #include <stdio.h>
  21. #include <sys/ioctl.h>
  22. #include <unistd.h>
  23. #include <string.h>
  24. #include <sys/socket.h>
  25. #include <sys/types.h>
  26. #include <stdlib.h>
  27. #include <stddef.h>
  28. #include <net/if.h>
  29. #include <ctype.h>
  30. #include <net/if_tun.h>
  31. #include <sys/stropts.h>
  32. #include <sys/sockio.h>
  33. #include <fcntl.h>
  34. #include <net/route.h>
  35. static void maskForPrefix(uint8_t mask[16], int prefix)
  36. {
  37. for (int i = 0; i < 16; i += 8) {
  38. if (i + 8 <= prefix) {
  39. mask[i] = 0xff;
  40. } else if (i > prefix) {
  41. mask[i] = 0x00;
  42. } else {
  43. mask[i] = (0xff << (i + 8 - prefix)) & 0xff;
  44. }
  45. }
  46. }
  47. struct RouteMessage {
  48. struct rt_msghdr header;
  49. struct sockaddr_in6 dest;
  50. struct sockaddr_in6 gateway;
  51. struct sockaddr_in6 netmask;
  52. };
  53. Assert_compileTime(sizeof(struct RouteMessage) == 172);
  54. static void setupRoute(const uint8_t address[16],
  55. int prefixLen,
  56. struct Log* logger,
  57. struct Except* eh)
  58. {
  59. struct RouteMessage rm = {
  60. .header = {
  61. .rtm_type = RTM_ADD,
  62. .rtm_version = RTM_VERSION,
  63. .rtm_seq = 0,
  64. .rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK,
  65. .rtm_msglen = sizeof(struct RouteMessage)
  66. },
  67. .dest = {
  68. .sin6_family = AF_INET6
  69. },
  70. .gateway = {
  71. .sin6_family = AF_INET6
  72. },
  73. .netmask = {
  74. .sin6_family = AF_INET6
  75. }
  76. };
  77. Bits_memcpyConst(&rm.dest.sin6_addr, address, 16);
  78. Bits_memcpyConst(&rm.gateway.sin6_addr, address, 16);
  79. maskForPrefix((uint8_t*) &rm.netmask.sin6_addr, prefixLen);
  80. int sock = socket(PF_ROUTE, SOCK_RAW, 0);
  81. if (sock == -1) {
  82. Except_throw(eh, "open route socket [%s]", strerror(errno));
  83. }
  84. ssize_t returnLen = write(sock, (char*) &rm, rm.header.rtm_msglen);
  85. if (returnLen < 0) {
  86. Except_throw(eh, "insert route [%s]", strerror(errno));
  87. } else if (returnLen < rm.header.rtm_msglen) {
  88. Except_throw(eh,
  89. "insert route returned only [%d] of [%d]",
  90. (int)returnLen, rm.header.rtm_msglen);
  91. }
  92. }
  93. static void addIp4Address(const char* interfaceName,
  94. const uint8_t address[4],
  95. int prefixLen,
  96. struct Log* logger,
  97. struct Except* eh)
  98. {
  99. // TODO: implement this and then remove the exception from TUNInterface_ipv4_root_test.c
  100. Except_throw(eh, "unimplemented");
  101. }
  102. static void addIp6Address(const char* interfaceName,
  103. const uint8_t address[16],
  104. int prefixLen,
  105. struct Log* logger,
  106. struct Except* eh)
  107. {
  108. struct lifreq ifr = {
  109. .lifr_ppa = 0,
  110. .lifr_flags = 0
  111. };
  112. char* error = NULL;
  113. struct sockaddr_in6* sin6 = (struct sockaddr_in6 *) &ifr.lifr_addr;
  114. maskForPrefix((uint8_t*) sin6->sin6_addr.s6_addr, prefixLen);
  115. ifr.lifr_addr.ss_family = AF_INET6;
  116. strncpy(ifr.lifr_name, interfaceName, LIFNAMSIZ);
  117. int udpSock = socket(AF_INET6, SOCK_DGRAM, 0);
  118. if (udpSock < 0) {
  119. error = "socket(AF_INET6, SOCK_DGRAM, 0)";
  120. } else if (ioctl(udpSock, SIOCSLIFNETMASK, (caddr_t)&ifr) < 0) {
  121. // set the netmask.
  122. error = "ioctl(SIOCSLIFNETMASK) (setting netmask)";
  123. }
  124. Bits_memcpyConst(&sin6->sin6_addr, address, 16);
  125. if (!error && ioctl(udpSock, SIOCSLIFADDR, (caddr_t)&ifr) < 0) {
  126. // set the ip address.
  127. error = "ioctl(SIOCSLIFADDR) (setting ipv6 address)";
  128. }
  129. if (!error && ioctl(udpSock, SIOCSLIFDSTADDR, (caddr_t)&ifr) < 0) {
  130. // set the destination address for the point-to-point connection
  131. // use the same as the source address since we're not really using it.
  132. error = "ioctl(SIOCGLIFDSTADDR) (setting point-to-point destination address)";
  133. }
  134. memset(sin6, 0, sizeof(struct sockaddr_in6));
  135. if (!error && ioctl(udpSock, SIOCGLIFFLAGS, (caddr_t)&ifr) < 0) {
  136. // get the flags for the device.
  137. error = "ioctl(SIOCGLIFFLAGS) (getting device flags)";
  138. }
  139. ifr.lifr_flags |= IFF_UP;
  140. if (!error && ioctl(udpSock, SIOCSLIFFLAGS, (caddr_t)&ifr) < 0) {
  141. // bring the interface up
  142. error = "ioctl(SIOCSLIFFLAGS) (bringing the interface up)";
  143. }
  144. if (error) {
  145. int err = errno;
  146. close(udpSock);
  147. Except_throw(eh, "%s [%s]",
  148. error, strerror(err));
  149. }
  150. close(udpSock);
  151. setupRoute(address, prefixLen, logger, eh);
  152. }
  153. void NetPlatform_addAddress(const char* interfaceName,
  154. const uint8_t* address,
  155. int prefixLen,
  156. int addrFam,
  157. struct Log* logger,
  158. struct Except* eh)
  159. {
  160. if (addrFam == Sockaddr_AF_INET6) {
  161. addIp6Address(interfaceName, address, prefixLen, logger, eh);
  162. } else if (addrFam == Sockaddr_AF_INET) {
  163. addIp4Address(interfaceName, address, prefixLen, logger, eh);
  164. } else {
  165. Assert_always(0);
  166. }
  167. }
  168. void NetPlatform_setMTU(const char* interfaceName,
  169. uint32_t mtu,
  170. struct Log* logger,
  171. struct Except* eh)
  172. {
  173. Except_throw(eh, "Not implemented in Illumos");
  174. }