NetPlatform_sunos.c 6.1 KB

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