1 /**********************************************************
2 SixXS - Automatic IPv6 Connectivity Configuration Utility
3 ***********************************************************
4 Copyright 2003-2005 SixXS - http://www.sixxs.net
5 ***********************************************************
6 common/ayiya.c - AYIYA - Anything In Anything
7 ***********************************************************
9 $Id: ayiya.c,v 1.15 2007-01-07 16:17:48 jeroen Exp $
10 $Date: 2007-01-07 16:17:48 $
11 **********************************************************/
21 struct in6_addr identity
;
22 sha1_byte hash
[SHA1_DIGEST_LENGTH
];
26 struct in_addr ayiya_ipv4_pop
; /* IPv4 remote endpoint */
27 struct in6_addr ayiya_ipv6_local
, /* IPv6 local endpoint */
28 ayiya_ipv6_pop
; /* IPv6 remote endpoint */
29 sha1_byte ayiya_hash
[SHA1_DIGEST_LENGTH
]; /* SHA1 Hash of the shared secret. */
31 TLSSOCKET ayiya_socket
= NULL
;
33 static const char reader_name
[] = "tundev->tun";
34 static const char writer_name
[] = "tun->tundev";
35 static const char beat_name
[] = "beat";
37 void ayiya_log(int level
, const char *what
, struct sockaddr_storage
*clientaddr
, socklen_t addrlen
, const char *fmt
, ...);
38 void ayiya_log(int level
, const char *what
, struct sockaddr_storage
*clientaddr
, socklen_t addrlen
, const char *fmt
, ...)
41 char clienthost
[NI_MAXHOST
];
42 char clientservice
[NI_MAXSERV
];
45 /* Clear them just in case */
46 memset(buf
, 0, sizeof(buf
));
47 memset(clienthost
, 0, sizeof(clienthost
));
48 memset(clientservice
, 0, sizeof(clientservice
));
53 ret
= getnameinfo((struct sockaddr
*)clientaddr
, addrlen
,
54 clienthost
, sizeof(clienthost
),
55 clientservice
, sizeof(clientservice
),
56 NI_NUMERICHOST
|NI_NUMERICSERV
);
59 dolog(LOG_ERR
, "ayiya_log() getnameinfo() ret: %d, errno: %u, %s\n", ret
, errno
, strerror(errno
));
63 /* Print the host+port this is coming from */
64 snprintf(buf
, sizeof(buf
), "[AYIYA-%s]%s%s%s%s : ",
66 clientaddr
? " [" : "",
67 clientaddr
? clienthost
: "" ,
68 clientaddr
? "]:" : "",
69 clientservice
? clientservice
: "");
71 /* Print the log message behind it */
73 vsnprintf(buf
+strlen(buf
), sizeof(buf
)-strlen(buf
), fmt
, ap
);
81 void ayiya_reader(char *buf
, unsigned int length
);
82 void ayiya_reader(char *buf
, unsigned int length
)
84 struct pseudo_ayh
*s
= (struct pseudo_ayh
*)buf
, s2
;
87 sha1_byte hash
[SHA1_DIGEST_LENGTH
];
88 struct sockaddr_in target
;
90 /* We tunnel over IPv4 */
91 memcpy(&target
.sin_addr
, &ayiya_ipv4_pop
, sizeof(target
.sin_addr
));
92 target
.sin_family
= AF_INET
;
93 target
.sin_port
= htons(atoi(AYIYA_PORT
));
95 /* Prefill some standard AYIYA values */
96 memset(&s
, 0, sizeof(s
));
97 s2
.ayh
.ayh_idlen
= 4; /* 2^4 = 16 bytes = 128 bits (IPv6 address) */
98 s2
.ayh
.ayh_idtype
= ayiya_id_integer
;
99 s2
.ayh
.ayh_siglen
= 5; /* 5*4 = 20 bytes = 160 bits (SHA1) */
100 s2
.ayh
.ayh_hshmeth
= ayiya_hash_sha1
;
101 s2
.ayh
.ayh_autmeth
= ayiya_auth_sharedsecret
;
102 s2
.ayh
.ayh_opcode
= ayiya_op_forward
;
103 s2
.ayh
.ayh_nextheader
= IPPROTO_IPV6
;
105 /* Our IPv6 side of this tunnel */
106 memcpy(&s2
.identity
, &ayiya_ipv6_local
, sizeof(s2
.identity
));
109 memcpy(&s2
.payload
, buf
, length
);
111 /* Fill in the current time */
112 s2
.ayh
.ayh_epochtime
= htonl((u_long
)time(NULL
));
115 * The hash of the shared secret needs to be in the
116 * spot where we later put the complete hash
118 memcpy(&s2
.hash
, ayiya_hash
, sizeof(s2
.hash
));
120 /* Generate a SHA1 */
122 /* Hash the complete AYIYA packet */
123 SHA1_Update(&sha1
, (sha1_byte
*)&s2
, sizeof(s2
)-sizeof(s2
.payload
)+length
);
124 /* Store the hash in the packets hash */
125 SHA1_Final(hash
, &sha1
);
127 /* Store the hash in the actual packet */
128 memcpy(&s2
.hash
, &hash
, sizeof(s2
.hash
));
130 /* Send it onto the network */
131 length
= sizeof(s2
)-sizeof(s2
.payload
)+length
;
132 #if defined(_FREEBSD) || defined(_DFBSD) || defined(_OPENBSD) || defined(_DARWIN) || defined(_NETBSD)
133 lenout
= send(ayiya_socket
->socket
, (const char *)&s2
, length
, 0);
135 lenout
= sendto(ayiya_socket
->socket
, (const char *)&s2
, length
, 0, (struct sockaddr
*)&target
, sizeof(target
));
139 ayiya_log(LOG_ERR
, reader_name
, NULL
, 0, "Error (%d) while sending %u bytes to network: %s (%d)\n", lenout
, length
, strerror(errno
), errno
);
141 else if (length
!= (unsigned int)lenout
)
143 ayiya_log(LOG_ERR
, reader_name
, NULL
, 0, "Only %u of %u bytes sent to network: %s (%s)\n", lenout
, length
, strerror(errno
), errno
);
147 struct tun_reader ayiya_tun
= { (TUN_PROCESS
)ayiya_reader
};
151 void *ayiya_writer(void UNUSED
*arg
);
152 void *ayiya_writer(void UNUSED
*arg
)
154 DWORD WINAPI
ayiya_writer(LPVOID arg
);
155 DWORD WINAPI
ayiya_writer(LPVOID arg
)
158 unsigned char buf
[2048];
159 struct pseudo_ayh
*s
= (struct pseudo_ayh
*)buf
;
160 struct sockaddr_storage ci
;
163 unsigned int payloadlen
= 0;
165 sha1_byte their_hash
[SHA1_DIGEST_LENGTH
],
166 our_hash
[SHA1_DIGEST_LENGTH
];
168 ayiya_log(LOG_INFO
, writer_name
, NULL
, 0, "(Socket to TUN) started\n");
170 /* Tun/TAP device is now running */
171 g_aiccu
->tunrunning
= true;
176 memset(buf
, 0, sizeof(buf
));
177 n
= recvfrom(ayiya_socket
->socket
, (char *)buf
, sizeof(buf
), 0, (struct sockaddr
*)&ci
, &cl
);
181 if (n
< (int)sizeof(struct ayiyahdr
))
183 ayiya_log(LOG_WARNING
, writer_name
, &ci
, cl
, "Received packet is too short");
187 if ( s
->ayh
.ayh_idlen
!= 4 ||
188 s
->ayh
.ayh_idtype
!= ayiya_id_integer
||
189 s
->ayh
.ayh_siglen
!= 5 ||
190 s
->ayh
.ayh_hshmeth
!= ayiya_hash_sha1
||
191 s
->ayh
.ayh_autmeth
!= ayiya_auth_sharedsecret
||
192 (s
->ayh
.ayh_nextheader
!= IPPROTO_IPV6
&&
193 s
->ayh
.ayh_nextheader
!= IPPROTO_NONE
) ||
194 (s
->ayh
.ayh_opcode
!= ayiya_op_forward
&&
195 s
->ayh
.ayh_opcode
!= ayiya_op_echo_request
&&
196 s
->ayh
.ayh_opcode
!= ayiya_op_echo_request_forward
))
198 /* Invalid AYIYA packet */
199 ayiya_log(LOG_ERR
, writer_name
, &ci
, cl
, "Dropping invalid AYIYA packet\n");
200 ayiya_log(LOG_ERR
, writer_name
, &ci
, cl
, "idlen: %u != %u\n", s
->ayh
.ayh_idlen
, 4);
201 ayiya_log(LOG_ERR
, writer_name
, &ci
, cl
, "idtype: %u != %u\n", s
->ayh
.ayh_idtype
, ayiya_id_integer
);
202 ayiya_log(LOG_ERR
, writer_name
, &ci
, cl
, "siglen: %u != %u\n", s
->ayh
.ayh_siglen
, 5);
203 ayiya_log(LOG_ERR
, writer_name
, &ci
, cl
, "hshmeth: %u != %u\n", s
->ayh
.ayh_hshmeth
, ayiya_hash_sha1
);
204 ayiya_log(LOG_ERR
, writer_name
, &ci
, cl
, "autmeth: %u != %u\n", s
->ayh
.ayh_autmeth
, ayiya_auth_sharedsecret
);
205 ayiya_log(LOG_ERR
, writer_name
, &ci
, cl
, "nexth : %u != %u || %u\n", s
->ayh
.ayh_nextheader
, IPPROTO_IPV6
, IPPROTO_NONE
);
206 ayiya_log(LOG_ERR
, writer_name
, &ci
, cl
, "opcode : %u != %u || %u || %u\n", s
->ayh
.ayh_opcode
, ayiya_op_forward
, ayiya_op_echo_request
, ayiya_op_echo_request_forward
);
210 if (memcmp(&s
->identity
, &ayiya_ipv6_pop
, sizeof(s
->identity
)) != 0)
212 memset(buf
, 0, sizeof(buf
));
213 inet_ntop(AF_INET6
, &s
->identity
, (char *)&buf
, sizeof(buf
));
214 ayiya_log(LOG_WARNING
, writer_name
, &ci
, cl
, "Received packet from a wrong identity \"%s\"\n", buf
);
218 /* Verify the epochtime */
219 i
= tic_checktime(ntohl(s
->ayh
.ayh_epochtime
));
222 memset(buf
, 0, sizeof(buf
));
223 inet_ntop(AF_INET6
, &s
->identity
, (char *)&buf
, sizeof(buf
));
224 ayiya_log(LOG_WARNING
, writer_name
, &ci
, cl
, "Time is %d seconds off for %s\n", i
, buf
);
228 /* How long is the payload? */
229 payloadlen
= n
- (sizeof(*s
) - sizeof(s
->payload
));
231 /* Save their hash */
232 memcpy(&their_hash
, &s
->hash
, sizeof(their_hash
));
234 /* Copy in our SHA1 hash */
235 memcpy(&s
->hash
, &ayiya_hash
, sizeof(s
->hash
));
237 /* Generate a SHA1 of the header + identity + shared secret */
239 /* Hash the Packet */
240 SHA1_Update(&sha1
, (sha1_byte
*)s
, n
);
242 SHA1_Final(our_hash
, &sha1
);
244 memcpy(&s
->hash
, &our_hash
, sizeof(s
->hash
));
246 /* Compare the SHA1's */
247 if (memcmp(&their_hash
, &our_hash
, sizeof(their_hash
)) != 0)
249 ayiya_log(LOG_WARNING
, writer_name
, &ci
, cl
, "Incorrect Hash received\n");
253 if (s
->ayh
.ayh_nextheader
== IPPROTO_IPV6
)
255 /* Verify that this is really IPv6 */
256 if (s
->payload
[0] >> 4 != 6)
258 ayiya_log(LOG_ERR
, writer_name
, &ci
, cl
, "Received packet didn't start with a 6, thus is not IPv6\n");
262 /* Forward the packet to the kernel */
263 tun_write(s
->payload
, payloadlen
);
267 /* Tun/TAP device is not running anymore */
268 g_aiccu
->tunrunning
= false;
277 /* Construct a beat and send it outwards */
278 void ayiya_beat(void)
281 sha1_byte hash
[SHA1_DIGEST_LENGTH
];
282 struct sockaddr_in target
;
286 /* We tunnel over IPv4 */
287 memcpy(&target
.sin_addr
, &ayiya_ipv4_pop
, sizeof(target
.sin_addr
));
288 target
.sin_family
= AF_INET
;
289 target
.sin_port
= htons(atoi(AYIYA_PORT
));
291 /* Prefill some standard AYIYA values */
292 memset(&s
, 0, sizeof(s
));
293 s
.ayh
.ayh_idlen
= 4; /* 2^4 = 16 bytes = 128 bits (IPv6 address) */
294 s
.ayh
.ayh_idtype
= ayiya_id_integer
;
295 s
.ayh
.ayh_siglen
= 5; /* 5*4 = 20 bytes = 160 bits (SHA1) */
296 s
.ayh
.ayh_hshmeth
= ayiya_hash_sha1
;
297 s
.ayh
.ayh_autmeth
= ayiya_auth_sharedsecret
;
298 s
.ayh
.ayh_opcode
= ayiya_op_noop
;
299 s
.ayh
.ayh_nextheader
= IPPROTO_NONE
;
301 /* Our IPv6 side of this tunnel */
302 memcpy(&s
.identity
, &ayiya_ipv6_local
, sizeof(s
.identity
));
306 /* Fill in the current time */
307 s
.ayh
.ayh_epochtime
= htonl((u_long
)time(NULL
));
309 /* Our IPv6 side of this tunnel */
310 memcpy(&s
.identity
, &ayiya_ipv6_local
, sizeof(s
.identity
));
313 * The hash of the shared secret needs to be in the
314 * spot where we later put the complete hash
316 memcpy(&s
.hash
, ayiya_hash
, sizeof(s
.hash
));
318 /* Generate a SHA1 */
320 /* Hash the complete AYIYA packet */
321 SHA1_Update(&sha1
, (sha1_byte
*)&s
, sizeof(s
)-sizeof(s
.payload
));
322 /* Store the hash in the packets hash */
323 SHA1_Final(hash
, &sha1
);
325 /* Store the hash in the actual packet */
326 memcpy(&s
.hash
, &hash
, sizeof(s
.hash
));
328 /* Send it onto the network */
329 n
= sizeof(s
)-sizeof(s
.payload
);
330 #if defined(_FREEBSD) || defined(_DFBSD) || defined(_OPENBSD) || defined(_DARWIN) || defined(_NETBSD)
331 lenout
= send(ayiya_socket
->socket
, (const char *)&s
, (unsigned int)n
, 0);
333 lenout
= sendto(ayiya_socket
->socket
, (const char *)&s
, (unsigned int)n
, 0, (struct sockaddr
*)&target
, sizeof(target
));
337 ayiya_log(LOG_ERR
, beat_name
, NULL
, 0, "Error (%d) while sending %u bytes sent to network: %s (%d)\n", lenout
, n
, strerror(errno
), errno
);
339 else if (n
!= lenout
)
341 ayiya_log(LOG_ERR
, beat_name
, NULL
, 0, "Only %u of %u bytes sent to network: %s (%d)\n", lenout
, n
, strerror(errno
), errno
);
345 bool ayiya(struct TIC_Tunnel
*hTunnel
)
348 struct addrinfo hints
, *res
, *ressave
;
356 /* Setup the tunnel */
357 if (!tun_start(&ayiya_tun
)) return false;
359 /* Resolve hTunnel entries */
360 memset(&hints
, 0, sizeof(struct addrinfo
));
361 hints
.ai_family
= AF_INET
;
362 hints
.ai_socktype
= SOCK_DGRAM
;
364 if (getaddrinfo(hTunnel
->sIPv4_POP
, AYIYA_PORT
, &hints
, &res
) != 0)
366 dolog(LOG_ERR
, "Couldn't resolve PoP IPv4 %s\n", hTunnel
->sIPv4_POP
);
372 if (res
->ai_family
!= AF_INET
)
377 memcpy(&ayiya_ipv4_pop
, &((struct sockaddr_in
*)res
->ai_addr
)->sin_addr
, 4);
380 freeaddrinfo(ressave
);
383 dolog(LOG_ERR
, "No valid IPv4 address for PoP address %s could be found\n", hTunnel
->sIPv4_POP
);
387 memset(&hints
, 0, sizeof(struct addrinfo
));
388 hints
.ai_family
= AF_INET6
;
389 if (getaddrinfo(hTunnel
->sIPv6_Local
, NULL
, &hints
, &res
) != 0)
391 dolog(LOG_ERR
, "Couldn't resolve Local IPv6 %s\n", hTunnel
->sIPv6_Local
);
397 if (res
->ai_family
!= AF_INET6
)
402 memcpy(&ayiya_ipv6_local
, &((struct sockaddr_in6
*)res
->ai_addr
)->sin6_addr
, 16);
405 freeaddrinfo(ressave
);
408 dolog(LOG_ERR
, "No valid IPv6 address for Local IPv6 address %s could be found\n", hTunnel
->sIPv6_Local
);
412 memset(&hints
, 0, sizeof(struct addrinfo
));
413 hints
.ai_family
= AF_INET6
;
414 if (getaddrinfo(hTunnel
->sIPv6_POP
, NULL
, &hints
, &res
) != 0)
416 dolog(LOG_ERR
, "Couldn't resolve Local IPv6 %s\n", hTunnel
->sIPv6_POP
);
422 if (res
->ai_family
!= AF_INET6
)
427 memcpy(&ayiya_ipv6_pop
, &((struct sockaddr_in6
*)res
->ai_addr
)->sin6_addr
, 16);
430 freeaddrinfo(ressave
);
433 dolog(LOG_ERR
, "No valid IPv6 address for POP IPv6 address %s could be found\n", hTunnel
->sIPv6_POP
);
437 if (!hTunnel
->sPassword
)
439 dolog(LOG_ERR
, "A password is required for using AYIYA tunnels\n");
443 /* Generate a SHA1 of the shared secret */
445 SHA1_Update(&sha1
, (const sha1_byte
*)hTunnel
->sPassword
, (unsigned int)strlen(hTunnel
->sPassword
));
446 SHA1_Final(ayiya_hash
, &sha1
);
448 /* Setup listening socket */
449 ayiya_socket
= connect_client(hTunnel
->sIPv4_POP
, AYIYA_PORT
, AF_INET
, SOCK_DGRAM
);
452 ayiya_log(LOG_ERR
, "start", NULL
, 0, "Connection error:: could not create connection to AYIYA server\n");
456 /* Let AICCU configure the thing */
457 if (!aiccu_setup(hTunnel
, false))
462 /* Show that we have started */
463 ayiya_log(LOG_INFO
, "start", NULL
, 0, "Anything in Anything (%s)\n", AYIYA_VERSION
);
465 /* Launch a thread for reader */
467 pthread_create(&thread
, NULL
, ayiya_writer
, (void *)hTunnel
);
469 h
= CreateThread(NULL
, 0, (LPTHREAD_START_ROUTINE
)ayiya_writer
, hTunnel
, 0, &pID
);