summaryrefslogtreecommitdiff
path: root/toxcore/LAN_discovery.c
diff options
context:
space:
mode:
Diffstat (limited to 'toxcore/LAN_discovery.c')
-rw-r--r--toxcore/LAN_discovery.c124
1 files changed, 64 insertions, 60 deletions
diff --git a/toxcore/LAN_discovery.c b/toxcore/LAN_discovery.c
index 1e4fa125..a4f1ccc2 100644
--- a/toxcore/LAN_discovery.c
+++ b/toxcore/LAN_discovery.c
@@ -30,60 +30,89 @@
30#define MAX_INTERFACES 16 30#define MAX_INTERFACES 16
31 31
32#ifdef __linux 32#ifdef __linux
33#ifndef TOX_ENABLE_IPV6 33
34/* Send packet to all broadcast addresses 34static int broadcast_count = -1;
35 * 35static IP_Port broadcast_ip_port[MAX_INTERFACES];
36 * return higher than 0 on success. 36
37 * return 0 on error. 37static void fetch_broadcast_info(uint16_t port)
38 *
39 * TODO: Make this work with IPv6 and remove the #ifndef TOX_ENABLE_IPV6.
40 */
41static uint32_t send_broadcasts(Networking_Core *net, uint16_t port, uint8_t *data, uint16_t length)
42{ 38{
43 /* Not sure how many platforms this will run on, 39 /* Not sure how many platforms this will run on,
44 * so it's wrapped in __linux for now. 40 * so it's wrapped in __linux for now.
41 * Definitely won't work like this on Windows...
45 */ 42 */
46 struct sockaddr_in *sock_holder = NULL; 43 broadcast_count = 0;
47 struct ifreq i_faces[MAX_INTERFACES]; 44 sock_t sock = 0;
48 struct ifconf ifconf;
49 int count = 0;
50 int sock = 0;
51 int i = 0;
52 45
53 /* Configure ifconf for the ioctl call. */ 46 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
54 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 47 return;
55 return 1;
56 }
57 48
49 /* Configure ifconf for the ioctl call. */
50 struct ifreq i_faces[MAX_INTERFACES];
58 memset(i_faces, 0, sizeof(struct ifreq) * MAX_INTERFACES); 51 memset(i_faces, 0, sizeof(struct ifreq) * MAX_INTERFACES);
59 52
53 struct ifconf ifconf;
60 ifconf.ifc_buf = (char *)i_faces; 54 ifconf.ifc_buf = (char *)i_faces;
61 ifconf.ifc_len = sizeof(i_faces); 55 ifconf.ifc_len = sizeof(i_faces);
62 count = ifconf.ifc_len / sizeof(struct ifreq);
63 56
64 if (ioctl(sock, SIOCGIFCONF, &ifconf) < 0) { 57 if (ioctl(sock, SIOCGIFCONF, &ifconf) < 0) {
65 return 1; 58 close(sock);
59 return;
66 } 60 }
67 61
62 /* ifconf.ifc_len is set by the ioctl() to the actual length used;
63 * on usage of the complete array the call should be repeated with
64 * a larger array, not done (640kB and 16 interfaces shall be
65 * enough, for everybody!)
66 */
67 int i, count = ifconf.ifc_len / sizeof(struct ifreq);
68
68 for (i = 0; i < count; i++) { 69 for (i = 0; i < count; i++) {
69 if (ioctl(sock, SIOCGIFBRDADDR, &i_faces[i]) < 0) { 70 /* there are interfaces with are incapable of broadcast */
70 return 1; 71 if (ioctl(sock, SIOCGIFBRDADDR, &i_faces[i]) < 0)
71 } 72 continue;
72 73
73 /* Just to clarify where we're getting the values from. */ 74 /* moot check: only AF_INET returned (backwards compat.) */
74 sock_holder = (struct sockaddr_in *)&i_faces[i].ifr_broadaddr; 75 if (i_faces[i].ifr_broadaddr.sa_family != AF_INET)
76 continue;
75 77
76 if (sock_holder != NULL) { 78 struct sockaddr_in *sock4 = (struct sockaddr_in *)&i_faces[i].ifr_broadaddr;
77 IP_Port ip_port = {{{{sock_holder->sin_addr.s_addr}}, port, 0}}; 79
78 sendpacket(net, ip_port, data, 1 + crypto_box_PUBLICKEYBYTES); 80 if (broadcast_count >= MAX_INTERFACES)
79 } 81 return;
82
83 IP_Port *ip_port = &broadcast_ip_port[broadcast_count];
84 ip_port->ip.family = AF_INET;
85 ip_port->ip.ip4.in_addr = sock4->sin_addr;
86 ip_port->port = port;
87 broadcast_count++;
80 } 88 }
81 89
82 close(sock); 90 close(sock);
83 return 0;
84} 91}
85#endif 92
86#endif 93/* Send packet to all IPv4 broadcast addresses
94 *
95 * return 1 if sent to at least one broadcast target.
96 * return 0 on failure to find any valid broadcast target.
97 */
98static uint32_t send_broadcasts(Networking_Core *net, uint16_t port, uint8_t *data, uint16_t length)
99{
100 /* fetch only once? on every packet? every X seconds?
101 * old: every packet, new: once */
102 if (broadcast_count < 0)
103 fetch_broadcast_info(port);
104
105 if (!broadcast_count)
106 return 0;
107
108 int i;
109
110 for (i = 0; i < broadcast_count; i++)
111 sendpacket(net, broadcast_ip_port[i], data, 1 + crypto_box_PUBLICKEYBYTES);
112
113 return 1;
114}
115#endif /* __linux */
87 116
88/* Return the broadcast ip. */ 117/* Return the broadcast ip. */
89static IP broadcast_ip(sa_family_t family_socket, sa_family_t family_broadcast) 118static IP broadcast_ip(sa_family_t family_socket, sa_family_t family_broadcast)
@@ -91,8 +120,6 @@ static IP broadcast_ip(sa_family_t family_socket, sa_family_t family_broadcast)
91 IP ip; 120 IP ip;
92 ip_reset(&ip); 121 ip_reset(&ip);
93 122
94#ifdef TOX_ENABLE_IPV6
95
96 if (family_socket == AF_INET6) { 123 if (family_socket == AF_INET6) {
97 if (family_broadcast == AF_INET6) { 124 if (family_broadcast == AF_INET6) {
98 ip.family = AF_INET6; 125 ip.family = AF_INET6;
@@ -116,14 +143,6 @@ static IP broadcast_ip(sa_family_t family_socket, sa_family_t family_broadcast)
116 } 143 }
117 } 144 }
118 145
119#else
120
121 if (family_socket == AF_INET)
122 if (family_broadcast == AF_INET)
123 ip.uint32 = INADDR_BROADCAST;
124
125#endif
126
127 return ip; 146 return ip;
128} 147}
129 148
@@ -132,13 +151,8 @@ static IP broadcast_ip(sa_family_t family_socket, sa_family_t family_broadcast)
132 */ 151 */
133int LAN_ip(IP ip) 152int LAN_ip(IP ip)
134{ 153{
135#ifdef TOX_ENABLE_IPV6
136
137 if (ip.family == AF_INET) { 154 if (ip.family == AF_INET) {
138 IP4 ip4 = ip.ip4; 155 IP4 ip4 = ip.ip4;
139#else
140 IP4 ip4 = ip;
141#endif
142 156
143 /* Loopback. */ 157 /* Loopback. */
144 if (ip4.uint8[0] == 127) 158 if (ip4.uint8[0] == 127)
@@ -161,9 +175,8 @@ int LAN_ip(IP ip)
161 && ip4.uint8[2] != 255) 175 && ip4.uint8[2] != 255)
162 return 0; 176 return 0;
163 177
164#ifdef TOX_ENABLE_IPV6 178 } else if (ip.family == AF_INET6) {
165 } else if (ip.family == AF_INET6) 179
166 {
167 /* autogenerated for each interface: FE80::* (up to FEBF::*) 180 /* autogenerated for each interface: FE80::* (up to FEBF::*)
168 FF02::1 is - according to RFC 4291 - multicast all-nodes link-local */ 181 FF02::1 is - according to RFC 4291 - multicast all-nodes link-local */
169 if (((ip.ip6.uint8[0] == 0xFF) && (ip.ip6.uint8[1] < 3) && (ip.ip6.uint8[15] == 1)) || 182 if (((ip.ip6.uint8[0] == 0xFF) && (ip.ip6.uint8[1] < 3) && (ip.ip6.uint8[15] == 1)) ||
@@ -179,8 +192,6 @@ int LAN_ip(IP ip)
179 } 192 }
180 } 193 }
181 194
182#endif
183
184 return -1; 195 return -1;
185} 196}
186 197
@@ -206,16 +217,12 @@ int send_LANdiscovery(uint16_t port, Net_Crypto *c)
206 memcpy(data + 1, c->self_public_key, crypto_box_PUBLICKEYBYTES); 217 memcpy(data + 1, c->self_public_key, crypto_box_PUBLICKEYBYTES);
207 218
208#ifdef __linux 219#ifdef __linux
209#ifndef TOX_ENABLE_IPV6
210 send_broadcasts(c->lossless_udp->net, port, data, 1 + crypto_box_PUBLICKEYBYTES); 220 send_broadcasts(c->lossless_udp->net, port, data, 1 + crypto_box_PUBLICKEYBYTES);
211#endif 221#endif
212#endif
213 int res = -1; 222 int res = -1;
214 IP_Port ip_port; 223 IP_Port ip_port;
215 ip_port.port = port; 224 ip_port.port = port;
216 225
217#ifdef TOX_ENABLE_IPV6
218
219 /* IPv6 multicast */ 226 /* IPv6 multicast */
220 if (c->lossless_udp->net->family == AF_INET6) { 227 if (c->lossless_udp->net->family == AF_INET6) {
221 ip_port.ip = broadcast_ip(AF_INET6, AF_INET6); 228 ip_port.ip = broadcast_ip(AF_INET6, AF_INET6);
@@ -227,9 +234,6 @@ int send_LANdiscovery(uint16_t port, Net_Crypto *c)
227 234
228 /* IPv4 broadcast (has to be IPv4-in-IPv6 mapping if socket is AF_INET6 */ 235 /* IPv4 broadcast (has to be IPv4-in-IPv6 mapping if socket is AF_INET6 */
229 ip_port.ip = broadcast_ip(c->lossless_udp->net->family, AF_INET); 236 ip_port.ip = broadcast_ip(c->lossless_udp->net->family, AF_INET);
230#else
231 ip_port.ip = broadcast_ip(AF_INET, AF_INET);
232#endif
233 237
234 if (ip_isset(&ip_port.ip)) 238 if (ip_isset(&ip_port.ip))
235 if (sendpacket(c->lossless_udp->net, ip_port, data, 1 + crypto_box_PUBLICKEYBYTES)) 239 if (sendpacket(c->lossless_udp->net, ip_port, data, 1 + crypto_box_PUBLICKEYBYTES))