[debugger] Ports from dotnet/runtime to maintain compatibility (#21653)
[mono-project.git] / mono / metadata / mono-route.c
blobba7e38ebf077d27591940d4947cbdbaae28ead39
1 /**
2 * \file
3 * Read the network routing tables using sysctl(3) calls
4 * Required for Unix-like systems that don't have Linux's /proc/net/route
6 * Author:
7 * Ben Woods (woodsb02@gmail.com)
8 */
10 #include "config.h"
12 #if HOST_DARWIN || HOST_BSD
14 #include <sys/types.h>
15 #include <sys/socket.h>
16 #include <net/if.h>
17 #include <net/if_dl.h>
18 #include <netinet/in.h>
19 #include <sys/param.h>
20 #include <sys/sysctl.h>
21 #include <stdlib.h>
22 #include <string.h>
24 #if HOST_IOS || HOST_WATCHOS || HOST_TVOS
25 // The iOS SDK does not provide the net/route.h header but using the Darwin version works fine.
26 #include "../../support/ios/net/route.h"
27 #else
28 #include <net/route.h>
29 #endif
31 static in_addr_t
32 gateway_from_rtm (struct rt_msghdr *rtm);
34 #include "object.h"
35 #include "icall-decl.h"
37 MonoBoolean
38 ves_icall_System_Net_NetworkInformation_MacOsIPInterfaceProperties_ParseRouteInfo (MonoStringHandle iface_handle, MonoArrayHandleOut gw_addr_list_handle, MonoError *error)
40 MonoString *iface = MONO_HANDLE_RAW (iface_handle);
41 MONO_HANDLE_ASSIGN_RAW (gw_addr_list_handle, NULL);
43 size_t needed;
44 in_addr_t in;
45 int mib [6];
46 int num_gws = 0, gwnum = 0;
47 unsigned int ifindex = 0;
48 char *buf = NULL;
49 char *next, *lim;
50 char *ifacename = NULL;
51 struct rt_msghdr *rtm;
52 MonoArray *gw_addr_list = NULL;
53 MonoStringHandle addr_string_handle = NULL_HANDLE_INIT; // FIXME probably overkill
54 MonoDomain *domain = mono_domain_get ();
55 MonoBoolean result = FALSE;
57 ifacename = mono_string_to_utf8_checked_internal (iface, error);
58 goto_if_nok (error, fail);
60 if ((ifindex = if_nametoindex (ifacename)) == 0)
61 goto fail;
63 // MIB array defining data to read from sysctl
64 mib [0] = CTL_NET; // Networking
65 mib [1] = PF_ROUTE; // Routing messages
66 mib [2] = 0; // Protocol number (always zero)
67 mib [3] = AF_INET; // Address family (IPv4)
68 mib [4] = NET_RT_DUMP; // Dump routing table
69 mib [5] = 0; //
71 // First sysctl call with oldp set to NULL to determine size of available data
72 if (sysctl(mib, G_N_ELEMENTS(mib), NULL, &needed, NULL, 0) < 0)
73 goto fail;
75 // Allocate suffcient memory for available data based on the previous sysctl call
76 if ((buf = g_malloc (needed)) == NULL)
77 goto fail;
79 // Second sysctl call to retrieve data into appropriately sized buffer
80 if (sysctl (mib, G_N_ELEMENTS (mib), buf, &needed, NULL, 0) < 0)
81 goto fail;
83 lim = buf + needed;
84 for (next = buf; next < lim; next += rtm->rtm_msglen) {
85 rtm = (struct rt_msghdr *)next;
86 if (rtm->rtm_version != RTM_VERSION
87 || rtm->rtm_index != ifindex
88 || (in = gateway_from_rtm (rtm)) == 0)
89 continue;
90 num_gws++;
93 gw_addr_list = mono_array_new_checked (domain, mono_get_string_class (), num_gws, error);
94 goto_if_nok (error, leave);
96 MONO_HANDLE_ASSIGN_RAW (gw_addr_list_handle, gw_addr_list);
98 addr_string_handle = MONO_HANDLE_NEW (MonoString, NULL); // FIXME probably overkill
100 for (next = buf; next < lim; next += rtm->rtm_msglen) {
101 rtm = (struct rt_msghdr *)next;
102 if (rtm->rtm_version != RTM_VERSION
103 || rtm->rtm_index != ifindex
104 || (in = gateway_from_rtm (rtm)) == 0)
105 continue;
107 MonoString *addr_string;
108 char addr [16], *ptr;
109 int len;
111 ptr = (char *) &in;
112 len = snprintf(addr, sizeof (addr), "%u.%u.%u.%u",
113 (unsigned char) ptr [0],
114 (unsigned char) ptr [1],
115 (unsigned char) ptr [2],
116 (unsigned char) ptr [3]);
118 if (len >= sizeof (addr) || len < 0)
119 // snprintf output truncated
120 continue;
122 addr_string = mono_string_new_checked (domain, addr, error);
123 goto_if_nok (error, leave);
124 MONO_HANDLE_ASSIGN_RAW (addr_string_handle, addr_string); // FIXME probably overkill
125 mono_array_setref_internal (gw_addr_list, gwnum, addr_string);
126 gwnum++;
128 leave:
129 result = is_ok (error);
130 fail:
131 g_free (ifacename);
132 g_free (buf);
133 return result;
136 static in_addr_t
137 gateway_from_rtm(struct rt_msghdr *rtm)
139 struct sockaddr *gw;
140 unsigned int l;
142 struct sockaddr *addr = (struct sockaddr *)(rtm + 1);
143 l = roundup(addr->sa_len, sizeof(long)); \
144 gw = (struct sockaddr *)((char *) addr + l); \
146 if (rtm->rtm_addrs & RTA_GATEWAY) {
147 if(gw->sa_family == AF_INET) {
148 struct sockaddr_in *sockin = (struct sockaddr_in *)gw;
149 return(sockin->sin_addr.s_addr);
153 return 0;
156 #else
158 #include "object.h"
159 #include "icall-decl.h"
161 MonoBoolean
162 ves_icall_System_Net_NetworkInformation_MacOsIPInterfaceProperties_ParseRouteInfo (MonoStringHandle iface_handle, MonoArrayHandleOut gw_addr_list_handle, MonoError *error)
164 mono_error_set_not_implemented (error, "");
165 return FALSE;
168 #endif
171 extern const char mono_route_empty_file_no_warning;
172 const char mono_route_empty_file_no_warning = 0;