- Socket handling revamped to use sockaddr_t.
- tinc can now tunnel over IPv6.
- Handle all addresses and subnets in network byte order.
Only convert them when they need to be printed.
- IPv6 subnets bigger than /128 now work.
- Use %s and strerror(errno) instead of %m.
Here are all valid variables, listed in alphabetical order.
The default value is given between parentheses.
.Bl -tag -width indent
+.It Va AddressFamily Li = ipv4 | ipv6 | any Pq ipv4
+This option affects the address family of listening and outgoing sockets.
+If
+.Qq any
+is selected, then the listening sockets will be IPv6 sockets,
+but on most platforms those will also accept IPv4 connections.
.It Va BindToInterface Li = Ar interface Bq experimental
If your computer has more than one network interface,
.Nm tinc
\input texinfo @c -*-texinfo-*-
-@c $Id: tinc.texi,v 1.8.4.20 2002/02/11 15:59:18 guus Exp $
+@c $Id: tinc.texi,v 1.8.4.21 2002/02/18 16:25:15 guus Exp $
@c %**start of header
@setfilename tinc.info
@settitle tinc Manual
<itimmermans@@bigfoot.com>, Guus Sliepen <guus@@sliepen.warande.net> and
Wessel Dankers <wsl@@nl.linux.org>.
-$Id: tinc.texi,v 1.8.4.20 2002/02/11 15:59:18 guus Exp $
+$Id: tinc.texi,v 1.8.4.21 2002/02/18 16:25:15 guus Exp $
Permission is granted to make and distribute verbatim copies of this
manual provided the copyright notice and this permission notice are
<itimmermans@@bigfoot.com>, Guus Sliepen <guus@@sliepen.warande.net> and
Wessel Dankers <wsl@@nl.linux.org>.
-$Id: tinc.texi,v 1.8.4.20 2002/02/11 15:59:18 guus Exp $
+$Id: tinc.texi,v 1.8.4.21 2002/02/18 16:25:15 guus Exp $
Permission is granted to make and distribute verbatim copies of this
manual provided the copyright notice and this permission notice are
@subsection Main configuration variables
@table @asis
+@cindex AddressFamily
+@item AddressFamily = <ipv4|ipv6|any> (ipv4)
+This option affects the address family of listening and outgoing sockets.
+If "any" is selected, then the listening sockets will be IPv6 sockets,
+but on most platforms those will also accept IPv4 connections.
+
@cindex BindToInterface
@item BindToInterface = <interface>
If you have more than one network interface in your computer, tinc will
src/connection.c
src/meta.c
src/net.c
+src/net_packet.c
+src/net_setup.c
+src/net_socket.c
src/netutl.c
src/protocol.c
src/protocol_auth.c
src/graph.c
src/linux/device.c
src/freebsd/device.c
-src/openbsd/device.c
src/solaris/device.c
+src/netbsd/device.c
+src/openbsd/device.c
msgid ""
msgstr ""
"Project-Id-Version: tinc 1.0-cvs\n"
-"POT-Creation-Date: 2002-02-11 16:57+0100\n"
+"POT-Creation-Date: 2002-02-18 17:09+0100\n"
"PO-Revision-Date: 2002-02-11 16:57+0100\n"
"Last-Translator: Guus Sliepen <guus@sliepen.warande.net>\n"
"Language-Team: Dutch <vertaling@nl.linux.org>\n"
msgid "Integer expected for configuration variable %s in %s line %d"
msgstr "Geheel getal verwacht voor configuratievariabele %s in %s regel %d"
-#: src/conf.c:219
+#: src/conf.c:218
#, c-format
-msgid "IP address expected for configuration variable %s in %s line %d"
-msgstr "IP adres verwacht voor configuratievariabele %s in %s regel %d"
+msgid ""
+"Hostname or IP address expected for configuration variable %s in %s line %d"
+msgstr ""
+"Hostnaam of IP adres verwacht voor configuratievariabele %s in %s regel %d"
-#: src/conf.c:233
+#: src/conf.c:235
#, c-format
msgid "Port number expected for configuration variable %s in %s line %d"
msgstr "Poortnummer verwacht voor configuratievariabele %s in %s regel %d"
-#: src/conf.c:249
+#: src/conf.c:251
#, c-format
msgid "Subnet expected for configuration variable %s in %s line %d"
msgstr "Subnet verwacht voor configuratievariabele %s in %s regel %d"
-#: src/conf.c:259
+#: src/conf.c:261
#, c-format
msgid ""
"Network address and mask length do not match for configuration variable %s "
"Netwerk adres en maskerlengte komen niet overeen bij configuratievariabele %"
"s in %s regel %d"
-#: src/conf.c:367
+#: src/conf.c:369
#, c-format
-msgid "Cannot open config file %s: %m"
-msgstr "Kan configuratie bestand %s niet openen: %m"
+msgid "Cannot open config file %s: %s"
+msgstr "Kan configuratie bestand %s niet openen: %s"
-#: src/conf.c:403
+#: src/conf.c:405
#, c-format
msgid "No value for variable `%s' on line %d while reading config file %s"
msgstr ""
"Geen waarde voor variabele `%s' op regel %d tijdens het lezen van "
"configuratie bestand %s"
-#: src/conf.c:436
+#: src/conf.c:438
#, c-format
-msgid "Failed to read `%s': %m"
-msgstr "Lezen van `%s' mislukte: %m"
+msgid "Failed to read `%s': %s"
+msgstr "Lezen van `%s' mislukte: %s"
-#: src/conf.c:464
+#: src/conf.c:465
#, c-format
msgid "`%s' is not an absolute path"
msgstr "`%s' is geen absoluut pad"
-#: src/conf.c:480 src/conf.c:513
+#: src/conf.c:481 src/conf.c:513
#, c-format
-msgid "Couldn't stat `%s': %m"
-msgstr "Kon `%s' niet statten: %m"
+msgid "Couldn't stat `%s': %s"
+msgstr "Kon `%s' niet statten: %s"
-#: src/conf.c:487 src/conf.c:523
+#: src/conf.c:487 src/conf.c:522
#, c-format
msgid "`%s' is owned by UID %d instead of %d"
msgstr "`%s' is eigendom van UID %d in plaats van %d"
-#: src/conf.c:494 src/conf.c:530
+#: src/conf.c:494 src/conf.c:529
#, c-format
msgid "Warning: `%s' is a symlink"
msgstr "Waarschuwing: `%s' is een symbolische link"
-#: src/conf.c:499 src/conf.c:535
+#: src/conf.c:499 src/conf.c:534
#, c-format
-msgid "Unable to read symbolic link `%s': %m"
-msgstr "Kan symbolische link `%s' niet lezen: %m"
+msgid "Unable to read symbolic link `%s': %s"
+msgstr "Kan symbolische link `%s' niet lezen: %s"
#. Accessible by others
-#: src/conf.c:546
+#: src/conf.c:545
#, c-format
msgid "`%s' has unsecure permissions"
msgstr "`%s' heeft onveilige permissies"
#. Ask for a file and/or directory name.
-#: src/conf.c:571
+#: src/conf.c:570
#, c-format
msgid "Please enter a file to save %s to [%s]: "
msgstr "Geef een bestand om de %s naar de schrijven [%s]: "
-#: src/conf.c:577
+#: src/conf.c:576
#, c-format
msgid "Error while reading stdin: %s\n"
msgstr "Fout tijdens lezen van standaardinvoer: %s\n"
-#: src/conf.c:603
+#: src/conf.c:602
#, c-format
msgid "Error opening file `%s': %s\n"
msgstr "Fout bij het openen van het bestand `%s': %s\n"
-#: src/conf.c:613
+#: src/conf.c:612
#, c-format
msgid ""
"The file `%s' (or any of the leading directories) has unsafe permissions.\n"
"bescherming.\n"
"Ik maak of overschrijf dit bestand niet.\n"
-#: src/connection.c:124
+#: src/connection.c:114
msgid "Connections:"
msgstr "Verbindingen:"
-#: src/connection.c:129
+#: src/connection.c:119
#, c-format
-msgid " %s at %s port %hd options %ld socket %d status %04x"
-msgstr " %s op %s poort %hd opties %d socket %d status %04x"
+msgid " %s at %s options %ld socket %d status %04x"
+msgstr " %s op %s opties %ld socket %d status %04x"
-#: src/connection.c:134
+#: src/connection.c:123
msgid "End of connections."
msgstr "Einde van verbindingen."
#: src/meta.c:63
#, c-format
-msgid "Sending meta data to %s (%s) failed: %m"
-msgstr "Fout tijdens verzenden metadata naar %s (%s): %m"
+msgid "Sending meta data to %s (%s) failed: %s"
+msgstr "Fout tijdens verzenden metadata naar %s (%s): %s"
#: src/meta.c:94
#, c-format
-msgid "This is a bug: %s:%d: %d:%m %s (%s)"
-msgstr "Dit is een programmeerfout: %s:%d: %d:%m %s (%s)"
+msgid "This is a bug: %s:%d: %d:%s %s (%s)"
+msgstr "Dit is een programmeerfout: %s:%d: %d:%s %s (%s)"
#: src/meta.c:100
#, c-format
#: src/meta.c:128
#, c-format
-msgid "Metadata socket read error for %s (%s): %m"
-msgstr "Fout op metadata socket voor %s (%s) tijdens lezen: %m"
+msgid "Metadata socket read error for %s (%s): %s"
+msgstr "Fout op metadata socket voor %s (%s) tijdens lezen: %s"
#: src/meta.c:202
#, c-format
msgid "Metadata read buffer overflow for %s (%s)"
msgstr "Metadata leesbuffer overloop voor %s (%s)"
-#: src/net.c:118
+#: src/net.c:109
+msgid "Purging unreachable nodes"
+msgstr "Verwijderen onbereikbare nodes"
+
+#: src/net.c:119
+#, c-format
+msgid "Purging node %s (%s)"
+msgstr "Verwijdering node %s (%s)"
+
+#: src/net.c:173
+#, c-format
+msgid "Closing connection with %s (%s)"
+msgstr "Beƫindigen verbinding met %s (%s)"
+
+#: src/net.c:244
+#, c-format
+msgid "%s (%s) didn't respond to PING"
+msgstr "%s (%s) antwoordde niet op ping"
+
+#: src/net.c:257
+#, c-format
+msgid "Timeout from %s (%s) during authentication"
+msgstr "Timeout van %s (%s) tijdens authenticatie"
+
+#: src/net.c:305
+#, c-format
+msgid "Error while connecting to %s (%s): %s"
+msgstr "Fout tijdens schrijven naar %s (%s): %s"
+
+#: src/net.c:370
+#, c-format
+msgid "Error while waiting for input: %s"
+msgstr "Fout tijdens wachten op invoer: %s"
+
+#: src/net.c:404
+msgid "Regenerating symmetric key"
+msgstr "Hergenereren symmetrische sleutel"
+
+#: src/net.c:421
+msgid "Flushing event queue"
+msgstr "Legen taakrij"
+
+#: src/net.c:434
+msgid "Rereading configuration file and restarting in 5 seconds"
+msgstr "Herlezen configuratiebestand en herstart in 5 seconden"
+
+#: src/net.c:441
+msgid "Unable to reread configuration file, exiting"
+msgstr "Kan configuratiebestand niet herlezen, beƫindigen"
+
+#: src/net_packet.c:106
#, c-format
msgid "Got unauthenticated packet from %s (%s)"
msgstr "Kreeg niet-geauthenticeerd pakket van %s (%s)"
-#: src/net.c:144
+#: src/net_packet.c:132
#, c-format
msgid "Got late or replayed packet from %s (%s), seqno %d"
msgstr "Kreeg laat of gedupliceerd pakket van %s (%s), seqno %d"
-#: src/net.c:161
+#: src/net_packet.c:149
#, c-format
msgid "Error while uncompressing packet from %s (%s)"
msgstr "Fout tijdens decomprimeren pakket van %s (%s)"
-#: src/net.c:188
+#: src/net_packet.c:176
#, c-format
msgid "Received packet of %d bytes from %s (%s)"
msgstr "Ontvangst pakket van %d bytes van %s (%s)"
-#: src/net.c:210
+#: src/net_packet.c:196
#, c-format
msgid "No valid key known yet for %s (%s), queueing packet"
msgstr ""
"Nog geen geldige sleutel bekend voor %s (%s), pakket wordt in wachtrij gezet"
-#: src/net.c:235
+#: src/net_packet.c:221
#, c-format
msgid "Error while compressing packet to %s (%s)"
msgstr "Fout tijdens comprimeren pakket naar %s (%s)"
-#: src/net.c:278
+#: src/net_packet.c:260
#, c-format
-msgid "Error sending packet to %s (%s): %m"
-msgstr "Fout tijdens verzenden pakket naar %s (%s): %m"
+msgid "Error sending packet to %s (%s): %s"
+msgstr "Fout tijdens verzenden pakket naar %s (%s): %s"
-#: src/net.c:293
+#: src/net_packet.c:275
#, c-format
msgid "Sending packet of %d bytes to %s (%s)"
msgstr "Verzending pakket van %d bytes naar %s (%s)"
-#: src/net.c:300
+#: src/net_packet.c:282
msgid "Packet is looping back to us!"
msgstr "Pakket komt terug naar ons!"
-#: src/net.c:309
+#: src/net_packet.c:291
#, c-format
msgid "Node %s (%s) is not reachable"
msgstr "Node %s (%s) is niet bereikbaar"
-#: src/net.c:317
+#: src/net_packet.c:299
#, c-format
msgid "Sending packet to %s via %s (%s)"
msgstr "Verzending pakket naar %s via %s (%s)"
-#: src/net.c:337
+#: src/net_packet.c:319
#, c-format
msgid "Broadcasting packet of %d bytes from %s (%s)"
msgstr "Verspreiding pakket van %d bytes van %s (%s)"
-#: src/net.c:354
+#: src/net_packet.c:336
#, c-format
msgid "Flushing queue for %s (%s)"
msgstr "Legen van wachtrij voor %s (%s)"
-#: src/net.c:379
-#, c-format
-msgid "Creating metasocket failed: %m"
-msgstr "Aanmaak van metasocket mislukt: %m"
-
-#: src/net.c:387 src/net.c:433 src/net.c:460 src/net.c:1091 src/process.c:258
-#: src/process.c:294
-#, c-format
-msgid "System call `%s' failed: %m"
-msgstr "Systeemaanroep `%s' mislukte: %m"
-
-#: src/net.c:407
-#, c-format
-msgid "Can't bind to interface %s: %m"
-msgstr "Kan niet aan interface %s binden: %m"
-
-#: src/net.c:426
+#: src/net_packet.c:358
#, c-format
-msgid "Can't bind to port %hd/tcp: %m"
-msgstr "Kan niet aan poort %hd/tcp binden: %m"
-
-#: src/net.c:450
-#, c-format
-msgid "Creating socket failed: %m"
-msgstr "Aanmaak socket mislukte: %m"
-
-#: src/net.c:473
-#, c-format
-msgid "Can't bind to port %hd/udp: %m"
-msgstr "Kan niet aan poort %hd/udp binden: %m"
-
-#: src/net.c:495
-#, c-format
-msgid "Trying to re-establish outgoing connection in %d seconds"
-msgstr "Poging tot herstellen van uitgaande verbinding over %d seconden"
-
-#: src/net.c:505
-#, c-format
-msgid "Trying to connect to %s (%s)"
-msgstr "Poging tot verbinden met %s (%s)"
-
-#: src/net.c:511
-#, c-format
-msgid "Creating socket for %s port %d failed: %m"
-msgstr "Aanmaken socket voor %s poort %d mislukt: %m"
-
-#: src/net.c:553
-#, c-format
-msgid "%s port %hd: %m"
-msgstr "%s poort %hd: %m"
-
-#: src/net.c:562
-#, c-format
-msgid "fcntl for %s port %d: %m"
-msgstr "fcntl voor %s poort %d: %m"
-
-#: src/net.c:568
-#, c-format
-msgid "Connected to %s port %hd"
-msgstr "Verbonden met %s poort %hd"
-
-#: src/net.c:586
-#, c-format
-msgid "Already connected to %s"
-msgstr "Reeds verbonden met %s"
+msgid "This is a bug: %s:%d: %d:%s"
+msgstr "Dit is een programmeerfout: %s:%d: %d:%s"
-#: src/net.c:599
+#: src/net_packet.c:364
#, c-format
-msgid "No address specified for %s"
-msgstr "Geen adres gespecificeerd voor %s"
+msgid "Incoming data socket error: %s"
+msgstr "Fout op socket voor inkomend verkeer: %s"
-#: src/net.c:611
+#: src/net_packet.c:370
#, c-format
-msgid "Error looking up `%s': %m"
-msgstr "Fout bij het opzoeken van `%s': %m"
+msgid "Receiving packet failed: %s"
+msgstr "Ontvangst pakket mislukt: %s"
-#: src/net.c:622
+#: src/net_packet.c:379
#, c-format
-msgid "Could not set up a meta connection to %s (%s)"
-msgstr "Kon geen metaverbinding aangaan met %s (%s)"
+msgid "Received UDP packet from unknown source %s"
+msgstr "Ontvangst UDP pakket van onbekende oorsprong %s"
-#: src/net.c:664
+#: src/net_setup.c:102
#, c-format
-msgid "Error reading RSA public key file `%s': %m"
-msgstr "Fout tijdens lezen RSA publieke sleutel bestand `%s': %m"
+msgid "Error reading RSA public key file `%s': %s"
+msgstr "Fout tijdens lezen RSA publieke sleutel bestand `%s': %s"
-#: src/net.c:674
+#: src/net_setup.c:112
#, c-format
-msgid "Reading RSA public key file `%s' failed: %m"
-msgstr "Lezen RSA publieke sleutel bestand `%s' mislukt: %m"
+msgid "Reading RSA public key file `%s' failed: %s"
+msgstr "Lezen RSA publieke sleutel bestand `%s' mislukt: %s"
-#: src/net.c:702
+#: src/net_setup.c:140
#, c-format
msgid "No public key for %s specified!"
msgstr "Geen publieke sleutel bekend voor %s gespecificeerd!"
-#: src/net.c:728
+#: src/net_setup.c:166
#, c-format
-msgid "Error reading RSA private key file `%s': %m"
-msgstr "Fout tijdens lezen RSA privƩ sleutel bestand `%s': %m"
+msgid "Error reading RSA private key file `%s': %s"
+msgstr "Fout tijdens lezen RSA privƩ sleutel bestand `%s': %s"
-#: src/net.c:738
+#: src/net_setup.c:176
#, c-format
-msgid "Reading RSA private key file `%s' failed: %m"
-msgstr "Fout tijdens lezen RSA privƩ sleutel bestand `%s': %m"
+msgid "Reading RSA private key file `%s' failed: %s"
+msgstr "Fout tijdens lezen RSA privƩ sleutel bestand `%s': %s"
-#: src/net.c:791 src/net.c:792
+#: src/net_setup.c:230 src/net_setup.c:231
msgid "MYSELF"
msgstr "MIJZELF"
-#: src/net.c:799
+#: src/net_setup.c:238
msgid "Name for tinc daemon required!"
msgstr "Naam voor tinc daemon verplicht!"
-#: src/net.c:805
+#: src/net_setup.c:244
msgid "Invalid name for myself!"
-msgstr "Ongelige naam voor mijzelf!"
+msgstr "Ongeldige naam voor mijzelf!"
-#: src/net.c:819
+#: src/net_setup.c:258
msgid "Cannot open host configuration file for myself!"
msgstr "Kan host configuratie bestand voor mijzelf niet openen!"
-#: src/net.c:829
+#: src/net_setup.c:268
msgid "Invalid public/private keypair!"
msgstr "Ongeldig publiek/privƩ sleutelpaar!"
-#: src/net.c:884
+#: src/net_setup.c:321
msgid "Invalid routing mode!"
-msgstr "Ongelige routing modus!"
+msgstr "Ongeldige routing modus!"
-#: src/net.c:896
-msgid "Unable to set up a listening TCP socket!"
-msgstr "Kon geen TCP luistersocket aanmaken!"
+#: src/net_setup.c:333
+msgid "Bogus maximum timeout!"
+msgstr "Onzinnige maximum timeout!"
-#: src/net.c:902
-msgid "Unable to set up a listening UDP socket!"
-msgstr "Kon geen UDP luistersocket aanmaken!"
+#: src/net_setup.c:350
+msgid "Invalid address family!"
+msgstr "Ongeldige adresfamilie!"
-#: src/net.c:918
+#: src/net_setup.c:372
msgid "Unrecognized cipher type!"
msgstr "Onbekend cipher type!"
-#: src/net.c:951
+#: src/net_setup.c:405
msgid "Unrecognized digest type!"
msgstr "Onbekend digest type!"
-#: src/net.c:965
+#: src/net_setup.c:419
msgid "MAC length exceeds size of digest!"
msgstr "MAC lengte is groter dan dat van digest!"
-#: src/net.c:970
+#: src/net_setup.c:424
msgid "Bogus MAC length!"
msgstr "Onzinnige MAC lengte!"
-#: src/net.c:984
+#: src/net_setup.c:438
msgid "Bogus compression level!"
msgstr "Onzinnig compressieniveau!"
-#: src/net.c:1000
+#: src/net_setup.c:464 src/net_socket.c:96 src/net_socket.c:131
+#: src/net_socket.c:157 src/process.c:258 src/process.c:293
#, c-format
-msgid "Ready: listening on port %hd"
-msgstr "Gereed: luisterend op poort %hd"
+msgid "System call `%s' failed: %s"
+msgstr "Systeemaanroep `%s' mislukte: %s"
-#: src/net.c:1104
+#: src/net_setup.c:470
+msgid "Unable to set up a listening TCP socket!"
+msgstr "Kon geen TCP luistersocket aanmaken!"
+
+#: src/net_setup.c:476
+msgid "Unable to set up a listening UDP socket!"
+msgstr "Kon geen UDP luistersocket aanmaken!"
+
+#: src/net_setup.c:482
#, c-format
-msgid "Connection from %s port %d"
-msgstr "Verbinding van %s poort %d"
+msgid "Ready: listening on port %s"
+msgstr "Gereed: luisterend op poort %s"
-#: src/net.c:1149
+#: src/net_socket.c:88
#, c-format
-msgid "This is a bug: %s:%d: %d:%m"
-msgstr "Dit is een programmeerfout: %s:%d: %d:%m"
+msgid "Creating metasocket failed: %s"
+msgstr "Aanmaak van metasocket mislukt: %s"
-#: src/net.c:1155
+#: src/net_socket.c:114 src/net_socket.c:168
#, c-format
-msgid "Incoming data socket error: %s"
-msgstr "Fout op socket voor inkomend verkeer: %s"
+msgid "Can't bind to interface %s: %s"
+msgstr "Kan niet aan interface %s binden: %s"
-#: src/net.c:1161
+#: src/net_socket.c:123
#, c-format
-msgid "Receiving packet failed: %m"
-msgstr "Ontvangst pakket mislukt: %m"
+msgid "Can't bind to %s/tcp: %s"
+msgstr "Kan niet aan %s/tcp binden: %s"
-#: src/net.c:1169
+#: src/net_socket.c:149
#, c-format
-msgid "Received UDP packet on port %hd from unknown source %x:%hd"
-msgstr "Ontvangst UDP pakket op poort %hd van onbekende oorsprong %x:%hd"
+msgid "Creating UDP socket failed: %s"
+msgstr "Aanmaak UDP socket mislukte: %s"
-#: src/net.c:1192
-msgid "Purging unreachable nodes"
-msgstr "Verwijderen onbereikbare nodes"
+#: src/net_socket.c:177
+#, c-format
+msgid "Can't bind to %s/udp: %s"
+msgstr "Kan niet aan %s/udp binden: %s"
-#: src/net.c:1202
+#: src/net_socket.c:200
#, c-format
-msgid "Purging node %s (%s)"
-msgstr "Verwijdering node %s (%s)"
+msgid "Trying to re-establish outgoing connection in %d seconds"
+msgstr "Poging tot herstellen van uitgaande verbinding over %d seconden"
-#: src/net.c:1256
+#: src/net_socket.c:209 src/net_socket.c:304
#, c-format
-msgid "Closing connection with %s (%s)"
-msgstr "Beƫindigen verbinding met %s (%s)"
+msgid "Trying to connect to %s (%s)"
+msgstr "Poging tot verbinden met %s (%s)"
-#: src/net.c:1327
+#: src/net_socket.c:215 src/net_socket.c:311
#, c-format
-msgid "%s (%s) didn't respond to PING"
-msgstr "%s (%s) antwoordde niet op ping"
+msgid "Creating socket for %s failed: %s"
+msgstr "Aanmaken socket voor %s mislukt: %s"
-#: src/net.c:1340
+#: src/net_socket.c:234 src/net_socket.c:350
#, c-format
-msgid "Timeout from %s (%s) during authentication"
-msgstr "Timeout van %s (%s) tijdens authenticatie"
+msgid "%s: %s"
+msgstr "%s: %s"
-#: src/net.c:1361
+#: src/net_socket.c:239 src/net_socket.c:249
#, c-format
-msgid "Accepting a new connection failed: %m"
-msgstr "Aanname van nieuwe verbinding is mislukt: %m"
+msgid "Connected to %s (%s)"
+msgstr "Verbonden met %s (%s)"
-#: src/net.c:1369
-msgid "Closed attempted connection"
-msgstr "Aangenomen verbinding verbroken"
+#: src/net_socket.c:268
+#, c-format
+msgid "Could not set up a meta connection to %s"
+msgstr "Kon geen metaverbinding aangaan met %s"
-#: src/net.c:1392
+#: src/net_socket.c:332
#, c-format
-msgid "Invalid name for outgoing connection in %s line %d"
-msgstr "Ongelige naam voor uitgaande verbinding in %s regel %d"
+msgid "fcntl for %s: %s"
+msgstr "fcntl voor %s: %s"
-#: src/net.c:1488
+#: src/net_socket.c:371
#, c-format
-msgid "Error while waiting for input: %m"
-msgstr "Fout tijdens wachten op invoer: %m"
+msgid "Already connected to %s"
+msgstr "Reeds verbonden met %s"
-#: src/net.c:1495
-msgid "Rereading configuration file and restarting in 5 seconds"
-msgstr "Herlezen configuratiebestand en herstart in 5 seconden"
+#: src/net_socket.c:386
+#, c-format
+msgid "No address specified for %s"
+msgstr "Geen adres gespecificeerd voor %s"
-#: src/net.c:1502
-msgid "Unable to reread configuration file, exiting"
-msgstr "Kan configuratiebestand niet herlezen, beƫindigen"
+#: src/net_socket.c:413
+#, c-format
+msgid "Accepting a new connection failed: %s"
+msgstr "Aanname van nieuwe verbinding is mislukt: %s"
-#: src/net.c:1534
-msgid "Regenerating symmetric key"
-msgstr "Hergenereren symmetrische sleutel"
+#: src/net_socket.c:425
+#, c-format
+msgid "Connection from %s"
+msgstr "Verbinding van %s"
-#: src/net.c:1544
-msgid "Flushing event queue"
-msgstr "Legen taakrij"
+#: src/net_socket.c:447
+#, c-format
+msgid "Invalid name for outgoing connection in %s line %d"
+msgstr "Ongeldige naam voor uitgaande verbinding in %s regel %d"
-#: src/netutl.c:84
+#: src/netutl.c:65 src/netutl.c:88
#, c-format
-msgid "Error looking up `%s': %s\n"
-msgstr "Fout bij het opzoeken van `%s': %s\n"
+msgid "Error looking up %s port %s: %s\n"
+msgstr "Fout bij het opzoeken van %s poort %s: %s\n"
+
+#: src/netutl.c:108
+#, c-format
+msgid "Error while translating addresses: %s"
+msgstr "Fout tijdens vertalen adressen: %s"
+
+#: src/netutl.c:128
+#, c-format
+msgid "Error while looking up hostname: %s"
+msgstr "Fout bij het opzoeken van hostnaam: %s"
+
+#: src/netutl.c:131
+#, c-format
+msgid "%s port %s"
+msgstr "%s poort %s"
+
+#: src/netutl.c:154
+#, c-format
+msgid "sockaddrcmp() was called with unknown address family %d, exitting!"
+msgstr ""
+"sockaddrcmp() werd aangeroepen met onbekende adresfamilie %d, beƫindigen!"
#: src/protocol.c:75
#, c-format
msgstr "Onzinnige data ontvangen van %s (%s)"
#: src/protocol_auth.c:69 src/protocol_auth.c:218 src/protocol_auth.c:311
-#: src/protocol_auth.c:367 src/protocol_auth.c:475 src/protocol_edge.c:85
-#: src/protocol_edge.c:215 src/protocol_key.c:78 src/protocol_key.c:116
+#: src/protocol_auth.c:367 src/protocol_auth.c:478 src/protocol_edge.c:98
+#: src/protocol_edge.c:230 src/protocol_key.c:78 src/protocol_key.c:116
#: src/protocol_key.c:184 src/protocol_misc.c:61 src/protocol_misc.c:91
#: src/protocol_misc.c:172 src/protocol_subnet.c:71 src/protocol_subnet.c:160
#, c-format
msgid "Got bad %s from %s (%s)"
msgstr "Kreeg verkeerde %s van %s (%s)"
-#: src/protocol_auth.c:77 src/protocol_edge.c:93 src/protocol_edge.c:99
-#: src/protocol_edge.c:224 src/protocol_edge.c:230 src/protocol_subnet.c:79
+#: src/protocol_auth.c:77 src/protocol_edge.c:106 src/protocol_edge.c:112
+#: src/protocol_edge.c:239 src/protocol_edge.c:245 src/protocol_subnet.c:79
#: src/protocol_subnet.c:87 src/protocol_subnet.c:168
#: src/protocol_subnet.c:186
#, c-format
msgid "Expected challenge reply: %s"
msgstr "Verwachtte antwoord op uitdaging: %s"
-#: src/protocol_auth.c:501
+#: src/protocol_auth.c:498
#, c-format
msgid "Established a second connection with %s (%s), closing old connection"
msgstr "Tweede verbinding met %s (%s) gemaakt, oude verbinding wordt gesloten"
msgid "Connection with %s (%s) activated"
msgstr "Verbinding met %s (%s) geactiveerd"
-#: src/protocol_edge.c:93 src/protocol_edge.c:99 src/protocol_edge.c:224
-#: src/protocol_edge.c:230 src/protocol_subnet.c:79 src/protocol_subnet.c:168
+#: src/protocol_edge.c:106 src/protocol_edge.c:112 src/protocol_edge.c:239
+#: src/protocol_edge.c:245 src/protocol_subnet.c:79 src/protocol_subnet.c:168
msgid "invalid name"
-msgstr "ongelige naam"
+msgstr "ongeldige naam"
-#: src/protocol_edge.c:142
+#: src/protocol_edge.c:157
#, c-format
msgid "Got %s from %s (%s) for ourself which does not match existing entry"
msgstr ""
"Kreeg %s van %s (%s) voor onszelf welke niet overeenkomt met reeds bekende"
-#: src/protocol_edge.c:149
+#: src/protocol_edge.c:164
#, c-format
msgid "Got %s from %s (%s) which does not match existing entry"
msgstr "Kreeg %s van %s (%s) welke niet overeenkomt met reeds bekende"
-#: src/protocol_edge.c:159
+#: src/protocol_edge.c:174
#, c-format
msgid "Got %s from %s (%s) for ourself which does not exist"
msgstr "Kreeg %s van %s (%s) voor onszelf welke niet bestaat"
-#: src/protocol_edge.c:241 src/protocol_edge.c:250 src/protocol_edge.c:261
+#: src/protocol_edge.c:256 src/protocol_edge.c:265 src/protocol_edge.c:276
#, c-format
msgid "Got %s from %s (%s) which does not appear in the edge tree"
msgstr "Kreeg %s van %s (%s) welke niet voorkomt in de edge tree"
-#: src/protocol_edge.c:268 src/protocol_subnet.c:115 src/protocol_subnet.c:211
+#: src/protocol_edge.c:283 src/protocol_subnet.c:115 src/protocol_subnet.c:211
#, c-format
msgid "Got %s from %s (%s) for ourself"
msgstr "Kreeg %s van %s (%s) voor onszelf"
msgid "Got %s from %s (%s) for %s which does not appear in his subnet tree"
msgstr "Kreeg %s van %s (%s) voor %s welke niet voorkomt in zijn subnet boom"
-#: src/subnet.c:109
+#: src/subnet.c:99
#, c-format
msgid "subnet_compare() was called with unknown subnet type %d, exitting!"
msgstr ""
"subnet_compare() werd aangeroepen met onbekend subnet type %d, beƫindigen!"
-#: src/subnet.c:327
-msgid "unknown subnet type"
-msgstr "onbekend subnet type"
+#: src/subnet.c:274
+#, c-format
+msgid "net2str() was called with unknown subnet type %d, exitting!"
+msgstr "net2str() werd aangeroepen met onbekend subnet type %d, beƫindigen!"
-#: src/subnet.c:411
+#: src/subnet.c:381
msgid "Subnet list:"
msgstr "Subnet lijst:"
-#: src/subnet.c:416
+#: src/subnet.c:386
#, c-format
msgid " %s owner %s"
msgstr " %s eigenaar %s"
-#: src/subnet.c:419
+#: src/subnet.c:389
msgid "End of subnet list."
msgstr "Einde van subnet lijst."
msgid "Restarting in %d seconds!"
msgstr "Herstart in %d seconden!"
-#: src/process.c:358 src/tincd.c:373
+#: src/process.c:356 src/tincd.c:373
msgid "Not restarting."
msgstr "Geen herstart."
msgid "tincd %s starting"
msgstr "tincd %s wordt gestart"
-#: src/process.c:266
+#: src/process.c:265
#, c-format
msgid "Executing script %s"
msgstr "Uitvoeren script %s"
-#: src/process.c:274
+#: src/process.c:273
#, c-format
msgid "Process %d (%s) exited with non-zero status %d"
msgstr "Proces %d (%s) beƫindigde met status %d"
-#: src/process.c:282
+#: src/process.c:281
#, c-format
msgid "Process %d (%s) was killed by signal %d (%s)"
msgstr "Proces %d (%s) was gestopt door signaal %d (%s)"
-#: src/process.c:288
+#: src/process.c:287
#, c-format
msgid "Process %d (%s) terminated abnormally"
msgstr "Proces %d (%s) abnormaal beƫindigd"
-#: src/process.c:313
+#: src/process.c:312
msgid "Got TERM signal"
msgstr "Kreeg TERM signaal"
-#: src/process.c:322
+#: src/process.c:321
msgid "Got QUIT signal"
msgstr "Kreeg QUIT signaal"
-#: src/process.c:329
+#: src/process.c:328
msgid "Got another SEGV signal: not restarting"
msgstr "Kreeg nog een SEGV signaal: geen herstart"
-#: src/process.c:338
+#: src/process.c:337
msgid "Got SEGV signal"
msgstr "Kreeg SEGV signaal"
-#: src/process.c:343
+#: src/process.c:342
msgid "Trying to re-execute in 5 seconds..."
msgstr "Poging tot herstarten over 5 seconden..."
-#: src/process.c:367
+#: src/process.c:365
msgid "Got HUP signal"
msgstr "Kreeg HUP signaal"
-#: src/process.c:376
+#: src/process.c:374
#, c-format
msgid "Reverting to old debug level (%d)"
msgstr "Herstellen van oud debug niveau (%d)"
-#: src/process.c:383
+#: src/process.c:381
#, c-format
msgid ""
"Temporarily setting debug level to 5. Kill me with SIGINT again to go back "
"Tijdelijk instellen debug niveau op 5. Zend nog een SIGINT signaal om niveau "
"%d te herstellen."
-#: src/process.c:394
+#: src/process.c:392
msgid "Got ALRM signal"
msgstr "Kreeg ALRM signaal"
-#: src/process.c:423
+#: src/process.c:421
#, c-format
msgid "Got unexpected signal %d (%s)"
msgstr "Kreeg onverwacht signaal %d (%s)"
-#: src/process.c:432
+#: src/process.c:430
#, c-format
msgid "Ignored signal %d (%s)"
msgstr "Signaal %d (%s) genegeerd"
-#: src/process.c:487
+#: src/process.c:485
#, c-format
msgid "Installing signal handler for signal %d (%s) failed: %s\n"
msgstr "Installeren van signaal afhandelaar voor signaal %d (%s) faalde: %s\n"
msgid "Learned new MAC address %hx:%hx:%hx:%hx:%hx:%hx"
msgstr "Nieuw MAC adres %hx:%hx:%hx:%hx:%hx:%hx geleerd"
-#: src/route.c:124
+#: src/route.c:116
#, c-format
-msgid "Cannot route packet: unknown destination address %d.%d.%d.%d"
-msgstr "Kan pakket niet routeren: onbekend doeladres %d.%d.%d.%d"
+msgid "Cannot route packet: unknown IPv4 destination address %d.%d.%d.%d"
+msgstr "Kan pakket niet routeren: onbekend IPv4 doeladres %d.%d.%d.%d"
-#: src/route.c:144
+#: src/route.c:136
#, c-format
msgid ""
"Cannot route packet: unknown IPv6 destination address %hx:%hx:%hx:%hx:%hx:%"
"Kan pakket niet routeren: onbekend IPv6 doeladres %hx:%hx:%hx:%hx:%hx:%hx:%"
"hx:%hx"
-#: src/route.c:189
+#: src/route.c:180
msgid "Cannot route packet: received unknown type ARP request"
msgstr "Kan pakket niet routeren: ontvangst van onbekend type ARP verzoek"
-#: src/route.c:203
+#: src/route.c:193
#, c-format
msgid "Cannot route packet: ARP request for unknown address %d.%d.%d.%d"
msgstr "Kan pakket niet routeren: ARP verzoek voor onbekend adres %d.%d.%d.%d"
-#: src/route.c:255
+#: src/route.c:245
#, c-format
msgid "Cannot route packet: unknown type %hx"
msgstr "Kan pakket niet routeren: onbekend type %hx"
#: src/node.c:166
#, c-format
msgid ""
-" %s at %s port %hd cipher %d digest %d maclength %d compression %d options %"
-"ld status %04x nexthop %s via %s"
+" %s at %s cipher %d digest %d maclength %d compression %d options %ld status "
+"%04x nexthop %s via %s"
msgstr ""
-" %s op %s poort %hd cipher %d digest %d maclengte %d compressie %d opties %"
-"ld status %04x nexthop %s via %s"
+" %s op %s cipher %d digest %d maclengte %d compressie %d opties %ld status %"
+"04x nexthop %s via %s"
#: src/node.c:171
msgid "End of nodes."
msgstr "Einde van nodes."
-#: src/edge.c:194
+#: src/edge.c:195
msgid "Edges:"
msgstr "Edges:"
-#: src/edge.c:201
+#: src/edge.c:204
#, c-format
-msgid " %s at %s port %hd - %s at %s port %hd options %ld weight %d"
-msgstr " %s op %s poort %hd - %s op %s poort %hd opties %ld gewicht %d"
+msgid " %s tcp at %s udp at %s - %s tcp at %s udp at %s options %ld weight %d"
+msgstr " %s tcp op %s udp op %s - %s tcp op %s udp op %s opties %ld gewicht %d"
-#: src/edge.c:209
+#: src/edge.c:214
msgid "End of edges."
msgstr "Einde van edges."
-#: src/graph.c:224
+#: src/graph.c:222
#, c-format
msgid "Node %s (%s) became reachable"
msgstr "Node %s (%s) werd bereikbaar"
-#: src/graph.c:233
+#: src/graph.c:231
#, c-format
msgid "Node %s (%s) became unreachable"
msgstr "Node %s (%s) is niet meer bereikbaar"
-#: src/freebsd/device.c:69 src/linux/device.c:88 src/openbsd/device.c:73
-#: src/solaris/device.c:74
+#: src/freebsd/device.c:70 src/linux/device.c:89 src/netbsd/device.c:74
+#: src/openbsd/device.c:74 src/solaris/device.c:75
#, c-format
-msgid "Could not open %s: %m"
-msgstr "Kon `%s' niet openen: %m"
+msgid "Could not open %s: %s"
+msgstr "Kon `%s' niet openen: %s"
-#: src/linux/device.c:113 src/linux/device.c:123
+#: src/linux/device.c:114 src/linux/device.c:124
msgid "Linux tun/tap device"
msgstr "Linux tun/tap apparaat"
-#: src/linux/device.c:121
+#: src/linux/device.c:122
#, c-format
msgid "Old ioctl() request was needed for %s"
msgstr "Oud ioctl() verzoek was nodig voor %s"
-#: src/linux/device.c:130
+#: src/linux/device.c:131
msgid "Linux ethertap device"
msgstr "Linux ethertap apparaat"
-#: src/freebsd/device.c:86 src/linux/device.c:134 src/openbsd/device.c:89
-#: src/solaris/device.c:131
+#: src/freebsd/device.c:87 src/linux/device.c:135 src/netbsd/device.c:90
+#: src/openbsd/device.c:90 src/solaris/device.c:132
#, c-format
msgid "%s is a %s"
msgstr "%s is een %s"
-#: src/freebsd/device.c:107 src/linux/device.c:157 src/linux/device.c:167
-#: src/openbsd/device.c:110 src/solaris/device.c:148
+#: src/freebsd/device.c:108 src/linux/device.c:158 src/linux/device.c:168
+#: src/netbsd/device.c:111 src/openbsd/device.c:111 src/solaris/device.c:149
#, c-format
-msgid "Error while reading from %s %s: %m"
-msgstr "Fout tijdens lezen van %s %s: %m"
+msgid "Error while reading from %s %s: %s"
+msgstr "Fout tijdens lezen van %s %s: %s"
-#: src/freebsd/device.c:116 src/linux/device.c:178 src/openbsd/device.c:125
-#: src/solaris/device.c:163
+#: src/freebsd/device.c:117 src/linux/device.c:179 src/netbsd/device.c:126
+#: src/openbsd/device.c:126 src/solaris/device.c:164
#, c-format
msgid "Read packet of %d bytes from %s"
msgstr "Pakket van %d bytes gelezen van %s"
-#: src/freebsd/device.c:127 src/linux/device.c:189 src/openbsd/device.c:138
-#: src/solaris/device.c:174
+#: src/freebsd/device.c:128 src/linux/device.c:190 src/netbsd/device.c:139
+#: src/openbsd/device.c:139 src/solaris/device.c:175
#, c-format
msgid "Writing packet of %d bytes to %s"
msgstr "Pakket van %d bytes geschreven naar %s"
-#: src/linux/device.c:196 src/linux/device.c:205 src/openbsd/device.c:148
-#: src/solaris/device.c:179
+#: src/linux/device.c:197 src/linux/device.c:206 src/netbsd/device.c:149
+#: src/openbsd/device.c:149 src/solaris/device.c:180
#, c-format
-msgid "Can't write to %s %s: %m"
-msgstr "Kan niet schrijven naar %s %s: %m"
+msgid "Can't write to %s %s: %s"
+msgstr "Kan niet schrijven naar %s %s: %s"
-#: src/freebsd/device.c:143 src/linux/device.c:218 src/openbsd/device.c:159
-#: src/solaris/device.c:191
+#: src/freebsd/device.c:144 src/linux/device.c:219 src/netbsd/device.c:160
+#: src/openbsd/device.c:160 src/solaris/device.c:192
#, c-format
msgid "Statistics for %s %s:"
msgstr "Statistieken voor %s %s:"
-#: src/freebsd/device.c:144 src/linux/device.c:219 src/openbsd/device.c:160
-#: src/solaris/device.c:192
+#: src/freebsd/device.c:145 src/linux/device.c:220 src/netbsd/device.c:161
+#: src/openbsd/device.c:161 src/solaris/device.c:193
#, c-format
msgid " total bytes in: %10d"
msgstr " totaal aantal bytes in: %10d"
-#: src/freebsd/device.c:145 src/linux/device.c:220 src/openbsd/device.c:161
-#: src/solaris/device.c:193
+#: src/freebsd/device.c:146 src/linux/device.c:221 src/netbsd/device.c:162
+#: src/openbsd/device.c:162 src/solaris/device.c:194
#, c-format
msgid " total bytes out: %10d"
msgstr " totaal aantal bytes uit: %10d"
-#: src/freebsd/device.c:84
+#: src/freebsd/device.c:85
msgid "FreeBSD tap device"
msgstr "FreeBSD tap apparaat"
-#: src/freebsd/device.c:132
+#: src/freebsd/device.c:133
#, c-format
-msgid "Error while writing to %s %s: %m"
-msgstr "Fout tijdens schrijven naar %s %s: %m"
-
-#: src/openbsd/device.c:87
-msgid "OpenBSD tun device"
-msgstr "OpenBSD tun apparaat"
+msgid "Error while writing to %s %s: %s"
+msgstr "Fout tijdens schrijven naar %s %s: %s"
-#: src/solaris/device.c:85
+#: src/solaris/device.c:86
#, c-format
-msgid "Could not open /dev/ip: %m"
-msgstr "Kon /dev/ip niet openen: %m"
+msgid "Could not open /dev/ip: %s"
+msgstr "Kon /dev/ip niet openen: %s"
-#: src/solaris/device.c:91
+#: src/solaris/device.c:92
#, c-format
-msgid "Can't assign new interface: %m"
-msgstr "Kan geen nieuwe interface toekennen: %m"
+msgid "Can't assign new interface: %s"
+msgstr "Kan geen nieuwe interface toekennen: %s"
-#: src/solaris/device.c:96
+#: src/solaris/device.c:97
#, c-format
-msgid "Could not open %s twice: %m"
-msgstr "Kon `%s' niet twee keer openen: %m"
+msgid "Could not open %s twice: %s"
+msgstr "Kon `%s' niet twee keer openen: %s"
-#: src/solaris/device.c:101
+#: src/solaris/device.c:102
#, c-format
-msgid "Can't push IP module: %m"
-msgstr "Kan IP module niet invoegen: %m"
+msgid "Can't push IP module: %s"
+msgstr "Kan IP module niet invoegen: %s"
-#: src/solaris/device.c:107
+#: src/solaris/device.c:108
#, c-format
-msgid "Can't set PPA %d: %m"
-msgstr "Kon PPA %d niet instellen: %m"
+msgid "Can't set PPA %d: %s"
+msgstr "Kon PPA %d niet instellen: %s"
-#: src/solaris/device.c:112
+#: src/solaris/device.c:113
#, c-format
-msgid "Can't link TUN device to IP: %m"
-msgstr "Kan TUN apparaat niet koppelen aan IP: %m"
+msgid "Can't link TUN device to IP: %s"
+msgstr "Kan TUN apparaat niet koppelen aan IP: %s"
-#: src/solaris/device.c:119
+#: src/solaris/device.c:120
msgid "Solaris tun device"
msgstr "Solaris tun apparaat"
+
+#: src/netbsd/device.c:88
+msgid "NetBSD tun device"
+msgstr "NetBSD tun apparaat"
+
+#: src/openbsd/device.c:88
+msgid "OpenBSD tun device"
+msgstr "OpenBSD tun apparaat"
## Produce this file with automake to get Makefile.in
-# $Id: Makefile.am,v 1.4.4.19 2002/02/10 21:57:52 guus Exp $
+# $Id: Makefile.am,v 1.4.4.20 2002/02/18 16:25:16 guus Exp $
sbin_PROGRAMS = tincd
EXTRA_DIST = linux/device.c freebsd/device.c openbsd/device.c solaris/device.c
-tincd_SOURCES = conf.c connection.c device.c edge.c event.c graph.c meta.c net.c netutl.c node.c process.c \
- protocol.c protocol_auth.c protocol_edge.c protocol_misc.c protocol_key.c protocol_subnet.c \
- route.c subnet.c tincd.c
+tincd_SOURCES = conf.c connection.c device.c edge.c event.c graph.c meta.c net.c net_packet.c net_setup.c \
+ net_socket.c netutl.c node.c process.c protocol.c protocol_auth.c protocol_edge.c protocol_misc.c \
+ protocol_key.c protocol_subnet.c route.c subnet.c tincd.c
INCLUDES = @INCLUDES@ -I$(top_builddir) -I$(top_srcdir)/lib -I$(top_srcdir)/intl
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: conf.c,v 1.9.4.52 2002/02/10 21:57:53 guus Exp $
+ $Id: conf.c,v 1.9.4.53 2002/02/18 16:25:16 guus Exp $
*/
#include "config.h"
int config_compare(config_t *a, config_t *b)
{
int result;
-
- result = strcmp(a->variable, b->variable);
-
+
+ result = strcasecmp(a->variable, b->variable);
+
if(result)
return result;
result = a->line - b->line;
-
+
if(result)
return result;
else
config_t *cfg;
cp
cfg = (config_t *)xmalloc_and_zero(sizeof(*cfg));
-
+
return cfg;
}
if(!found)
return NULL;
-
+
if(strcmp(found->variable, variable))
return NULL;
config_t *found;
cp
node = avl_search_node(config_tree, cfg);
-
+
if(node)
{
if(node->next)
return found;
}
}
-
+
return NULL;
}
-
+
int get_config_bool(config_t *cfg, int *result)
{
cp
if(sscanf(cfg->value, "%d", result) == 1)
return 1;
-
+
syslog(LOG_ERR, _("Integer expected for configuration variable %s in %s line %d"),
cfg->variable, cfg->file, cfg->line);
return 0;
if(!cfg)
return 0;
- *result = cfg->value;
+ *result = xstrdup(cfg->value);
return 1;
}
-int get_config_address(config_t *cfg, ipv4_t **result)
+int get_config_address(config_t *cfg, struct addrinfo **result)
{
- ipv4_t *ip;
+ struct addrinfo *ai;
cp
if(!cfg)
return 0;
- ip = xmalloc(sizeof(*ip));
- *ip = str2address(cfg->value);
+ ai = str2addrinfo(cfg->value, NULL, 0);
- if(ip)
+ if(ai)
{
- *result = ip;
+ *result = ai;
return 1;
}
- syslog(LOG_ERR, _("IP address expected for configuration variable %s in %s line %d"),
+ syslog(LOG_ERR, _("Hostname or IP address expected for configuration variable %s in %s line %d"),
cfg->variable, cfg->file, cfg->line);
return 0;
}
return 0;
if(sscanf(cfg->value, "%hu", result) == 1)
- return 1;
-
+ {
+ *result = htons(*result);
+ return 1;
+ }
+
syslog(LOG_ERR, _("Port number expected for configuration variable %s in %s line %d"),
cfg->variable, cfg->file, cfg->line);
return 0;
cfg->variable, cfg->file, cfg->line);
return 0;
}
-
+
/* Teach newbies what subnets are... */
- if(subnet->type == SUBNET_IPV4)
- if((subnet->net.ipv4.address & subnet->net.ipv4.mask) != subnet->net.ipv4.address)
- {
- syslog(LOG_ERR, _("Network address and mask length do not match for configuration variable %s in %s line %d"),
- cfg->variable, cfg->file, cfg->line);
- free(subnet);
- return 0;
- }
+ if(((subnet->type == SUBNET_IPV4) && maskcheck((char *)&subnet->net.ipv4.address, subnet->net.ipv4.masklength, sizeof(ipv4_t)))
+ || ((subnet->type == SUBNET_IPV6) && maskcheck((char *)&subnet->net.ipv6.address, subnet->net.ipv6.masklength, sizeof(ipv6_t))))
+ {
+ syslog(LOG_ERR, _("Network address and mask length do not match for configuration variable %s in %s line %d"),
+ cfg->variable, cfg->file, cfg->line);
+ free(subnet);
+ return 0;
+ }
*result = subnet;
-
+
return 1;
}
Read exactly one line and strip the trailing newline if any. If the
file was on EOF, return NULL. Otherwise, return all the data in a
dynamically allocated buffer.
-
+
If line is non-NULL, it will be used as an initial buffer, to avoid
unnecessary mallocing each time this function is called. If buf is
given, and buf needs to be expanded, the var pointed to by buflen
int lineno = 0, ignore = 0;
config_t *cfg;
size_t bufsize;
-
+
cp
if((fp = fopen (fname, "r")) == NULL)
{
- syslog(LOG_ERR, _("Cannot open config file %s: %m"), fname);
+ syslog(LOG_ERR, _("Cannot open config file %s: %s"), fname, strerror(errno));
return -3;
}
bufsize = 100;
buffer = xmalloc(bufsize);
-
+
for(;;)
{
if((line = readline(fp, &buffer, &bufsize)) == NULL)
if(!strcmp(variable, "-----BEGIN"))
ignore = 1;
-
+
if(!ignore)
{
if(((value = strtok(NULL, "\t\n\r =")) == NULL) || value[0] == '#')
x = read_config_file(config_tree, fname);
if(x == -1) /* System error: complain */
{
- syslog(LOG_ERR, _("Failed to read `%s': %m"),
- fname);
+ syslog(LOG_ERR, _("Failed to read `%s': %s"), fname, strerror(errno));
}
free(fname);
cp
- return x;
+ return x;
}
int isadir(const char* f)
}
p = strrchr(file, '/');
-
+
if(p == file) /* It's in the root */
p++;
-
+
x = *p;
*p = '\0';
check1:
if(lstat(f, &s) < 0)
{
- syslog(LOG_ERR, _("Couldn't stat `%s': %m"),
- f);
+ syslog(LOG_ERR, _("Couldn't stat `%s': %s"), f, strerror(errno));
return 0;
}
if(readlink(f, l, MAXBUFSIZE) < 0)
{
- syslog(LOG_ERR, _("Unable to read symbolic link `%s': %m"), f);
+ syslog(LOG_ERR, _("Unable to read symbolic link `%s': %s"), f, strerror(errno));
return 0;
}
-
+
f = l;
goto check1;
}
*p = x;
f = file;
-
+
check2:
if(lstat(f, &s) < 0 && errno != ENOENT)
{
- syslog(LOG_ERR, _("Couldn't stat `%s': %m"),
- f);
+ syslog(LOG_ERR, _("Couldn't stat `%s': %s"), f, strerror(errno));
return 0;
}
-
+
if(errno == ENOENT)
return 1;
if(readlink(f, l, MAXBUFSIZE) < 0)
{
- syslog(LOG_ERR, _("Unable to read symbolic link `%s': %m"), f);
+ syslog(LOG_ERR, _("Unable to read symbolic link `%s': %s"), f, strerror(errno));
return 0;
}
-
+
f = l;
goto check2;
}
f);
return 0;
}
-
+
return 1;
}
{
/* The directory is a relative path or a filename. */
char *p;
-
+
directory = get_current_dir_name();
asprintf(&p, "%s/%s", directory, fn);
free(fn);
}
umask(0077); /* Disallow everything for group and other */
-
+
/* Open it first to keep the inode busy */
if((r = fopen(fn, mode)) == NULL)
{
free(fn);
return NULL;
}
-
+
/* Then check the file for nasty attacks */
if(!is_safe_path(fn)) /* Do not permit any directories that are
readable or writeable by other users. */
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: conf.h,v 1.6.4.31 2002/02/10 21:57:53 guus Exp $
+ $Id: conf.h,v 1.6.4.32 2002/02/18 16:25:16 guus Exp $
*/
#ifndef __TINC_CONF_H__
#define __TINC_CONF_H__
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+
#include <avl_tree.h>
#include "net.h"
#include "subnet.h"
extern int get_config_int(config_t *, int *);
extern int get_config_port(config_t *, port_t *);
extern int get_config_string(config_t *, char **);
-extern int get_config_address(config_t *, ipv4_t **);
+extern int get_config_address(config_t *, struct addrinfo **);
struct subnet_t; /* Needed for next line. */
extern int get_config_subnet(config_t *, struct subnet_t **);
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: connection.c,v 1.1.2.27 2002/02/10 21:57:53 guus Exp $
+ $Id: connection.c,v 1.1.2.28 2002/02/18 16:25:16 guus Exp $
*/
#include "config.h"
int connection_compare(connection_t *a, connection_t *b)
{
- return a->socket - b->socket;
+ return a - b;
}
void init_connections(void)
cp
}
-connection_t *lookup_connection(ipv4_t address, port_t port)
-{
- connection_t c;
-cp
- c.address = address;
- c.port = port;
-
- return avl_search(connection_tree, &c);
-}
-
void dump_connections(void)
{
avl_node_t *node;
for(node = connection_tree->head; node; node = node->next)
{
c = (connection_t *)node->data;
- syslog(LOG_DEBUG, _(" %s at %s port %hd options %ld socket %d status %04x"),
- c->name, c->hostname, c->port, c->options,
- c->socket, c->status);
+ syslog(LOG_DEBUG, _(" %s at %s options %ld socket %d status %04x"),
+ c->name, c->hostname, c->options, c->socket, c->status);
}
syslog(LOG_DEBUG, _("End of connections."));
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: connection.h,v 1.1.2.24 2002/02/10 21:57:53 guus Exp $
+ $Id: connection.h,v 1.1.2.25 2002/02/18 16:25:16 guus Exp $
*/
#ifndef __TINC_CONNECTION_H__
typedef struct connection_status_t {
int pinged:1; /* sent ping */
int active:1; /* 1 if active.. */
+ int connecting:1; /* 1 if we are waiting for a non-blocking connect() to finish */
int termreq:1; /* the termination of this connection was requested */
int remove:1; /* Set to 1 if you want this connection removed */
int timeout:1; /* 1 if gotten timeout */
typedef struct connection_t {
char *name; /* name he claims to have */
- ipv4_t address; /* his real (internet) ip */
- port_t port; /* port number of meta connection */
+ sockaddr_t address; /* his real (internet) ip */
char *hostname; /* the hostname of its real ip */
int protocol_version; /* used protocol */
struct outgoing_t *outgoing; /* used to keep track of outgoing connections */
struct node_t *node; /* node associated with the other end */
- struct edge_t *edge; /* edge associated with this connection */
+ struct edge_t *edge; /* edge associated with this connection */
RSA *rsa_key; /* his public/private key */
EVP_CIPHER *incipher; /* Cipher he will use to send data to us */
extern void free_connection(connection_t *);
extern void connection_add(connection_t *);
extern void connection_del(connection_t *);
-extern connection_t *lookup_connection(ipv4_t, short unsigned int);
extern void dump_connections(void);
extern int read_connection_config(connection_t *);
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: edge.c,v 1.1.2.6 2002/02/10 21:57:54 guus Exp $
+ $Id: edge.c,v 1.1.2.7 2002/02/18 16:25:16 guus Exp $
*/
#include "config.h"
int result;
result = strcmp(a->from.node->name, b->from.node->name);
-
+
if(result)
return result;
else
{
int result;
char *name_a1, *name_a2, *name_b1, *name_b2;
-
+
if(strcmp(a->from.node->name, a->to.node->name) < 0)
name_a1 = a->from.node->name, name_a2 = a->to.node->name;
else
name_b1 = b->to.node->name, name_b2 = b->from.node->name;
result = strcmp(name_a1, name_b1);
-
+
if(result)
return result;
else
int edge_weight_compare(edge_t *a, edge_t *b)
{
int result;
-
+
result = a->weight - b->weight;
-
+
if(result)
return result;
else
{
avl_node_t *node;
edge_t *e;
- char *from_address, *to_address;
+ char *from_tcp, *from_udp;
+ char *to_tcp, *to_udp;
cp
syslog(LOG_DEBUG, _("Edges:"));
for(node = edge_tree->head; node; node = node->next)
{
e = (edge_t *)node->data;
- from_address = address2str(e->from.address);
- to_address = address2str(e->to.address);
- syslog(LOG_DEBUG, _(" %s at %s port %hd - %s at %s port %hd options %ld weight %d"),
- e->from.node->name, from_address, e->from.port,
- e->to.node->name, to_address, e->to.port,
+ from_tcp = sockaddr2hostname(&e->from.tcpaddress);
+ from_udp = sockaddr2hostname(&e->from.udpaddress);
+ to_tcp = sockaddr2hostname(&e->to.tcpaddress);
+ to_udp = sockaddr2hostname(&e->to.udpaddress);
+ syslog(LOG_DEBUG, _(" %s tcp at %s udp at %s - %s tcp at %s udp at %s options %ld weight %d"),
+ e->from.node->name, from_tcp, from_udp,
+ e->to.node->name, to_tcp, to_udp,
e->options, e->weight);
- free(from_address);
- free(to_address);
+ free(from_tcp);
+ free(from_udp);
+ free(to_tcp);
+ free(to_udp);
}
-
+
syslog(LOG_DEBUG, _("End of edges."));
cp
}
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: edge.h,v 1.1.2.5 2002/02/10 21:57:54 guus Exp $
+ $Id: edge.h,v 1.1.2.6 2002/02/18 16:25:16 guus Exp $
*/
#ifndef __TINC_EDGE_H__
#include <avl_tree.h>
+#include "net.h"
#include "node.h"
#include "connection.h"
typedef struct halfconnection_t {
struct node_t *node; /* node associated with this end of the connection */
-
- ipv4_t address; /* real (internet) ip on this end of the meta connection */
- port_t port; /* port number of this end of the meta connection */
+ sockaddr_t tcpaddress; /* real (internet) ip on this end of the meta connection */
+ sockaddr_t udpaddress; /* real (internet) ip on this end of the vpn connection */
} halfconnection_t;
typedef struct edge_t {
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: device.c,v 1.1.2.3 2002/02/11 12:33:01 guus Exp $
+ $Id: device.c,v 1.1.2.4 2002/02/18 16:25:19 guus Exp $
*/
#include "config.h"
#include <stdio.h>
+#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
cp
if((device_fd = open(device, O_RDWR | O_NONBLOCK)) < 0)
{
- syslog(LOG_ERR, _("Could not open %s: %m"), device);
+ syslog(LOG_ERR, _("Could not open %s: %s"), device, strerror(errno));
return -1;
}
cp
cp
if((lenin = read(device_fd, packet->data, MTU)) <= 0)
{
- syslog(LOG_ERR, _("Error while reading from %s %s: %m"), device_info, device);
+ syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info, device, strerror(errno));
return -1;
}
if(write(device_fd, packet->data, packet->len) < 0)
{
- syslog(LOG_ERR, _("Error while writing to %s %s: %m"), device_info, device);
+ syslog(LOG_ERR, _("Error while writing to %s %s: %s"), device_info, device, strerror(errno));
return -1;
}
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: graph.c,v 1.1.2.6 2002/02/10 21:57:54 guus Exp $
+ $Id: graph.c,v 1.1.2.7 2002/02/18 16:25:16 guus Exp $
*/
/* We need to generate two trees from the graph:
to_hc.node->nexthop = (n->nexthop == myself) ? to_hc.node : n->nexthop;
to_hc.node->via = (e->options & OPTION_INDIRECT || n->via != n) ? n->via : to_hc.node;
to_hc.node->options = e->options;
- if(to_hc.node->address != to_hc.address || to_hc.node->port != to_hc.port)
+ if(sockaddrcmp(&to_hc.node->address, &to_hc.udpaddress))
{
node = avl_unlink(node_udp_tree, to_hc.node);
- to_hc.node->address = to_hc.address;
- to_hc.node->port = to_hc.port;
+ to_hc.node->address = to_hc.udpaddress;
if(to_hc.node->hostname)
free(to_hc.node->hostname);
- to_hc.node->hostname = hostlookup(htonl(to_hc.address));
+ to_hc.node->hostname = sockaddr2hostname(&to_hc.udpaddress);
avl_insert_node(node_udp_tree, node);
}
- to_hc.node->port = to_hc.port;
node = avl_alloc_node();
node->data = to_hc.node;
avl_insert_before(todo_tree, from, node);
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: device.c,v 1.1.2.6 2002/02/11 12:33:01 guus Exp $
+ $Id: device.c,v 1.1.2.7 2002/02/18 16:25:19 guus Exp $
*/
#include "config.h"
#include <stdio.h>
+#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
cp
if((device_fd = open(device, O_RDWR | O_NONBLOCK)) < 0)
{
- syslog(LOG_ERR, _("Could not open %s: %m"), device);
+ syslog(LOG_ERR, _("Could not open %s: %s"), device, strerror(errno));
return -1;
}
cp
{
if((lenin = read(device_fd, packet->data, MTU)) <= 0)
{
- syslog(LOG_ERR, _("Error while reading from %s %s: %m"), device_info, device);
+ syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info, device, strerror(errno));
return -1;
}
{
if((lenin = read(device_fd, packet->data - 2, MTU + 2)) <= 0)
{
- syslog(LOG_ERR, _("Error while reading from %s %s: %m"), device_info, device);
+ syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info, device, strerror(errno));
return -1;
}
{
if(write(device_fd, packet->data, packet->len) < 0)
{
- syslog(LOG_ERR, _("Can't write to %s %s: %m"), device_info, device);
+ syslog(LOG_ERR, _("Can't write to %s %s: %s"), device_info, device, strerror(errno));
return -1;
}
}
*(short int *)(packet->data - 2) = packet->len;
if(write(device_fd, packet->data - 2, packet->len + 2) < 0)
{
- syslog(LOG_ERR, _("Can't write to %s %s: %m"), device_info, device);
+ syslog(LOG_ERR, _("Can't write to %s %s: %s"), device_info, device, strerror(errno));
return -1;
}
}
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: meta.c,v 1.1.2.23 2002/02/12 14:36:45 guus Exp $
+ $Id: meta.c,v 1.1.2.24 2002/02/18 16:25:16 guus Exp $
*/
#include "config.h"
if(write(c->socket, bufp, length) < 0)
{
- syslog(LOG_ERR, _("Sending meta data to %s (%s) failed: %m"), c->name, c->hostname);
+ syslog(LOG_ERR, _("Sending meta data to %s (%s) failed: %s"), c->name, c->hostname, strerror(errno));
return -1;
}
cp
cp
if(getsockopt(c->socket, SOL_SOCKET, SO_ERROR, &x, &l) < 0)
{
- syslog(LOG_ERR, _("This is a bug: %s:%d: %d:%m %s (%s)"), __FILE__, __LINE__, c->socket,
+ syslog(LOG_ERR, _("This is a bug: %s:%d: %d:%s %s (%s)"), __FILE__, __LINE__, c->socket, strerror(errno),
c->name, c->hostname);
return -1;
}
if(errno==EINTR)
return 0;
else
- syslog(LOG_ERR, _("Metadata socket read error for %s (%s): %m"),
- c->name, c->hostname);
+ syslog(LOG_ERR, _("Metadata socket read error for %s (%s): %s"),
+ c->name, c->hostname, strerror(errno));
return -1;
}
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: net.c,v 1.35.4.155 2002/02/12 14:36:45 guus Exp $
+ $Id: net.c,v 1.35.4.156 2002/02/18 16:25:16 guus Exp $
*/
#include "config.h"
#include <net/if.h>
#include <openssl/rand.h>
-#include <openssl/evp.h>
-#include <openssl/pem.h>
-#include <openssl/hmac.h>
-#ifndef HAVE_RAND_PSEUDO_BYTES
-#define RAND_pseudo_bytes RAND_bytes
-#endif
-
-#include <zlib.h>
-
-#include <utils.h>
-#include <xalloc.h>
-#include <avl_tree.h>
-#include <list.h>
-
-#include "conf.h"
-#include "connection.h"
-#include "meta.h"
-#include "net.h"
-#include "netutl.h"
-#include "process.h"
-#include "protocol.h"
-#include "subnet.h"
-#include "graph.h"
-#include "process.h"
-#include "route.h"
-#include "device.h"
-#include "event.h"
-
-#include "system.h"
-
-int maxtimeout = 900;
-int seconds_till_retry = 5;
-
-int tcp_socket = -1;
-int udp_socket = -1;
-
-int keylifetime = 0;
-int keyexpires = 0;
-
-int do_prune = 0;
-int do_purge = 0;
-int sighup = 0;
-int sigalrm = 0;
-
-#define MAX_SEQNO 1073741824
-
-/* VPN packet I/O */
-
-void receive_udppacket(node_t *n, vpn_packet_t *inpkt)
-{
- vpn_packet_t pkt1, pkt2;
- vpn_packet_t *pkt[] = {&pkt1, &pkt2, &pkt1, &pkt2};
- int nextpkt = 0;
- vpn_packet_t *outpkt = pkt[0];
- int outlen, outpad;
- long int complen = MTU + 12;
- EVP_CIPHER_CTX ctx;
- char hmac[EVP_MAX_MD_SIZE];
-cp
- /* Check the message authentication code */
-
- if(myself->digest && myself->maclength)
- {
- inpkt->len -= myself->maclength;
- HMAC(myself->digest, myself->key, myself->keylength, (char *)&inpkt->seqno, inpkt->len, hmac, NULL);
- if(memcmp(hmac, (char *)&inpkt->seqno + inpkt->len, myself->maclength))
- {
- syslog(LOG_DEBUG, _("Got unauthenticated packet from %s (%s)"), n->name, n->hostname);
- return;
- }
- }
-
- /* Decrypt the packet */
-
- if(myself->cipher)
- {
- outpkt = pkt[nextpkt++];
-
- EVP_DecryptInit(&ctx, myself->cipher, myself->key, myself->key + myself->cipher->key_len);
- EVP_DecryptUpdate(&ctx, (char *)&outpkt->seqno, &outlen, (char *)&inpkt->seqno, inpkt->len);
- EVP_DecryptFinal(&ctx, (char *)&outpkt->seqno + outlen, &outpad);
-
- outpkt->len = outlen + outpad;
- inpkt = outpkt;
- }
-
- /* Check the sequence number */
-
- inpkt->len -= sizeof(inpkt->seqno);
- inpkt->seqno = ntohl(inpkt->seqno);
-
- if(inpkt->seqno <= n->received_seqno)
- {
- syslog(LOG_DEBUG, _("Got late or replayed packet from %s (%s), seqno %d"), n->name, n->hostname, inpkt->seqno);
- return;
- }
-
- n->received_seqno = inpkt->seqno;
-
- if(n->received_seqno > MAX_SEQNO)
- keyexpires = 0;
-
- /* Decompress the packet */
-
- if(myself->compression)
- {
- outpkt = pkt[nextpkt++];
-
- if(uncompress(outpkt->data, &complen, inpkt->data, inpkt->len) != Z_OK)
- {
- syslog(LOG_ERR, _("Error while uncompressing packet from %s (%s)"), n->name, n->hostname);
- return;
- }
-
- outpkt->len = complen;
- inpkt = outpkt;
- }
-
- receive_packet(n, inpkt);
-cp
-}
-
-void receive_tcppacket(connection_t *c, char *buffer, int len)
-{
- vpn_packet_t outpkt;
-cp
- outpkt.len = len;
- memcpy(outpkt.data, buffer, len);
-
- receive_packet(c->node, &outpkt);
-cp
-}
-
-void receive_packet(node_t *n, vpn_packet_t *packet)
-{
-cp
- if(debug_lvl >= DEBUG_TRAFFIC)
- syslog(LOG_DEBUG, _("Received packet of %d bytes from %s (%s)"), packet->len, n->name, n->hostname);
-
- route_incoming(n, packet);
-cp
-}
-
-void send_udppacket(node_t *n, vpn_packet_t *inpkt)
-{
- vpn_packet_t pkt1, pkt2;
- vpn_packet_t *pkt[] = {&pkt1, &pkt2, &pkt1, &pkt2};
- int nextpkt = 0;
- vpn_packet_t *outpkt;
- int outlen, outpad;
- long int complen = MTU + 12;
- EVP_CIPHER_CTX ctx;
- struct sockaddr_in to;
- socklen_t tolen = sizeof(to);
- vpn_packet_t *copy;
-cp
- if(!n->status.validkey)
- {
- if(debug_lvl >= DEBUG_TRAFFIC)
- syslog(LOG_INFO, _("No valid key known yet for %s (%s), queueing packet"),
- n->name, n->hostname);
-
- /* Since packet is on the stack of handle_tap_input(),
- we have to make a copy of it first. */
-
- copy = xmalloc(sizeof(vpn_packet_t));
- memcpy(copy, inpkt, sizeof(vpn_packet_t));
-
- list_insert_tail(n->queue, copy);
-
- if(!n->status.waitingforkey)
- send_req_key(n->nexthop->connection, myself, n);
-
- return;
- }
-
- /* Compress the packet */
-
- if(n->compression)
- {
- outpkt = pkt[nextpkt++];
-
- if(compress2(outpkt->data, &complen, inpkt->data, inpkt->len, n->compression) != Z_OK)
- {
- syslog(LOG_ERR, _("Error while compressing packet to %s (%s)"), n->name, n->hostname);
- return;
- }
-
- outpkt->len = complen;
- inpkt = outpkt;
- }
-
- /* Add sequence number */
-
- inpkt->seqno = htonl(++(n->sent_seqno));
- inpkt->len += sizeof(inpkt->seqno);
-
- /* Encrypt the packet */
-
- if(n->cipher)
- {
- outpkt = pkt[nextpkt++];
-
- EVP_EncryptInit(&ctx, n->cipher, n->key, n->key + n->cipher->key_len);
- EVP_EncryptUpdate(&ctx, (char *)&outpkt->seqno, &outlen, (char *)&inpkt->seqno, inpkt->len);
- EVP_EncryptFinal(&ctx, (char *)&outpkt->seqno + outlen, &outpad);
-
- outpkt->len = outlen + outpad;
- inpkt = outpkt;
- }
-
- /* Add the message authentication code */
-
- if(n->digest && n->maclength)
- {
- HMAC(n->digest, n->key, n->keylength, (char *)&inpkt->seqno, inpkt->len, (char *)&inpkt->seqno + inpkt->len, &outlen);
- inpkt->len += n->maclength;
- }
-
- /* Send the packet */
-
- to.sin_family = AF_INET;
- to.sin_addr.s_addr = htonl(n->address);
- to.sin_port = htons(n->port);
-
- if((sendto(udp_socket, (char *)&inpkt->seqno, inpkt->len, 0, (const struct sockaddr *)&to, tolen)) < 0)
- {
- syslog(LOG_ERR, _("Error sending packet to %s (%s): %m"),
- n->name, n->hostname);
- return;
- }
-cp
-}
-
-/*
- send a packet to the given vpn ip.
-*/
-void send_packet(node_t *n, vpn_packet_t *packet)
-{
- node_t *via;
-cp
- if(debug_lvl >= DEBUG_TRAFFIC)
- syslog(LOG_ERR, _("Sending packet of %d bytes to %s (%s)"),
- packet->len, n->name, n->hostname);
-
- if(n == myself)
- {
- if(debug_lvl >= DEBUG_TRAFFIC)
- {
- syslog(LOG_NOTICE, _("Packet is looping back to us!"));
- }
-
- return;
- }
-
- if(!n->status.reachable)
- {
- if(debug_lvl >= DEBUG_TRAFFIC)
- syslog(LOG_INFO, _("Node %s (%s) is not reachable"),
- n->name, n->hostname);
- return;
- }
-
- via = (n->via == myself)?n->nexthop:n->via;
-
- if(via != n && debug_lvl >= DEBUG_TRAFFIC)
- syslog(LOG_ERR, _("Sending packet to %s via %s (%s)"),
- n->name, via->name, n->via->hostname);
-
- if((myself->options | via->options) & OPTION_TCPONLY)
- {
- if(send_tcppacket(via->connection, packet))
- terminate_connection(via->connection, 1);
- }
- else
- send_udppacket(via, packet);
-}
-
-/* Broadcast a packet using the minimum spanning tree */
-
-void broadcast_packet(node_t *from, vpn_packet_t *packet)
-{
- avl_node_t *node;
- connection_t *c;
-cp
- if(debug_lvl >= DEBUG_TRAFFIC)
- syslog(LOG_INFO, _("Broadcasting packet of %d bytes from %s (%s)"),
- packet->len, from->name, from->hostname);
-
- for(node = connection_tree->head; node; node = node->next)
- {
- c = (connection_t *)node->data;
- if(c->status.active && c->status.mst && c != from->nexthop->connection)
- send_packet(c->node, packet);
- }
-cp
-}
-
-void flush_queue(node_t *n)
-{
- list_node_t *node, *next;
-cp
- if(debug_lvl >= DEBUG_TRAFFIC)
- syslog(LOG_INFO, _("Flushing queue for %s (%s)"), n->name, n->hostname);
-
- for(node = n->queue->head; node; node = next)
- {
- next = node->next;
- send_udppacket(n, (vpn_packet_t *)node->data);
- list_delete_node(n->queue, node);
- }
-cp
-}
-
-/* Setup sockets */
-
-int setup_listen_socket(port_t port)
-{
- int nfd, flags;
- struct sockaddr_in a;
- int option;
- ipv4_t *address;
-#ifdef HAVE_LINUX
- char *interface;
-#endif
-cp
- if((nfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
- {
- syslog(LOG_ERR, _("Creating metasocket failed: %m"));
- return -1;
- }
-
- flags = fcntl(nfd, F_GETFL);
- if(fcntl(nfd, F_SETFL, flags | O_NONBLOCK) < 0)
- {
- close(nfd);
- syslog(LOG_ERR, _("System call `%s' failed: %m"),
- "fcntl");
- return -1;
- }
-
- /* Optimize TCP settings */
-
- option = 1;
- setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option));
- setsockopt(nfd, SOL_SOCKET, SO_KEEPALIVE, &option, sizeof(option));
-#ifdef HAVE_LINUX
- setsockopt(nfd, SOL_TCP, TCP_NODELAY, &option, sizeof(option));
-
- option = IPTOS_LOWDELAY;
- setsockopt(nfd, SOL_IP, IP_TOS, &option, sizeof(option));
-
- if(get_config_string(lookup_config(config_tree, "BindToInterface"), &interface))
- if(setsockopt(nfd, SOL_SOCKET, SO_BINDTODEVICE, interface, strlen(interface)))
- {
- close(nfd);
- syslog(LOG_ERR, _("Can't bind to interface %s: %m"), interface);
- return -1;
- }
-#endif
-
- memset(&a, 0, sizeof(a));
- a.sin_family = AF_INET;
- a.sin_addr.s_addr = htonl(INADDR_ANY);
- a.sin_port = htons(port);
-
- if(get_config_address(lookup_config(config_tree, "BindToAddress"), &address))
- {
- a.sin_addr.s_addr = htonl(*address);
- free(address);
- }
-
- if(bind(nfd, (struct sockaddr *)&a, sizeof(struct sockaddr)))
- {
- close(nfd);
- syslog(LOG_ERR, _("Can't bind to port %hd/tcp: %m"), port);
- return -1;
- }
-
- if(listen(nfd, 3))
- {
- close(nfd);
- syslog(LOG_ERR, _("System call `%s' failed: %m"),
- "listen");
- return -1;
- }
-cp
- return nfd;
-}
-
-int setup_vpn_in_socket(port_t port)
-{
- int nfd, flags;
- struct sockaddr_in a;
- const int one = 1;
-cp
- if((nfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
- {
- close(nfd);
- syslog(LOG_ERR, _("Creating socket failed: %m"));
- return -1;
- }
-
- setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
-
- flags = fcntl(nfd, F_GETFL);
- if(fcntl(nfd, F_SETFL, flags | O_NONBLOCK) < 0)
- {
- close(nfd);
- syslog(LOG_ERR, _("System call `%s' failed: %m"),
- "fcntl");
- return -1;
- }
-
- memset(&a, 0, sizeof(a));
- a.sin_family = AF_INET;
- a.sin_port = htons(port);
- a.sin_addr.s_addr = htonl(INADDR_ANY);
-
- if(bind(nfd, (struct sockaddr *)&a, sizeof(struct sockaddr)))
- {
- close(nfd);
- syslog(LOG_ERR, _("Can't bind to port %hd/udp: %m"), port);
- return -1;
- }
-cp
- return nfd;
-}
-
-void retry_outgoing(outgoing_t *outgoing)
-{
- event_t *event;
-cp
- outgoing->timeout += 5;
- if(outgoing->timeout > maxtimeout)
- outgoing->timeout = maxtimeout;
-
- event = new_event();
- event->handler = (event_handler_t)setup_outgoing_connection;
- event->time = time(NULL) + outgoing->timeout;
- event->data = outgoing;
- event_add(event);
-
- if(debug_lvl >= DEBUG_CONNECTIONS)
- syslog(LOG_NOTICE, _("Trying to re-establish outgoing connection in %d seconds"), outgoing->timeout);
-cp
-}
-
-int setup_outgoing_socket(connection_t *c)
-{
- int flags;
- struct sockaddr_in a;
-cp
- if(debug_lvl >= DEBUG_CONNECTIONS)
- syslog(LOG_INFO, _("Trying to connect to %s (%s)"), c->name, c->hostname);
-
- c->socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
-
- if(c->socket == -1)
- {
- syslog(LOG_ERR, _("Creating socket for %s port %d failed: %m"),
- c->hostname, c->port);
- return -1;
- }
-
- /* Bind first to get a fix on our source port???
-
- a.sin_family = AF_INET;
- a.sin_port = htons(0);
- a.sin_addr.s_addr = htonl(INADDR_ANY);
-
- if(bind(c->socket, (struct sockaddr *)&a, sizeof(struct sockaddr)))
- {
- close(c->socket);
- syslog(LOG_ERR, _("System call `%s' failed: %m"), "bind");
- return -1;
- }
-
- */
-
- /* Optimize TCP settings?
-
- option = 1;
- setsockopt(c->socket, SOL_SOCKET, SO_KEEPALIVE, &option, sizeof(option));
-#ifdef HAVE_LINUX
- setsockopt(c->socket, SOL_TCP, TCP_NODELAY, &option, sizeof(option));
-
- option = IPTOS_LOWDELAY;
- setsockopt(c->socket, SOL_IP, IP_TOS, &option, sizeof(option));
-#endif
-
- */
-
- /* Connect */
-
- a.sin_family = AF_INET;
- a.sin_port = htons(c->port);
- a.sin_addr.s_addr = htonl(c->address);
-
- if(connect(c->socket, (struct sockaddr *)&a, sizeof(a)) == -1)
- {
- close(c->socket);
- syslog(LOG_ERR, _("%s port %hd: %m"), c->hostname, c->port);
- return -1;
- }
-
- flags = fcntl(c->socket, F_GETFL);
-
- if(fcntl(c->socket, F_SETFL, flags | O_NONBLOCK) < 0)
- {
- close(c->socket);
- syslog(LOG_ERR, _("fcntl for %s port %d: %m"),
- c->hostname, c->port);
- return -1;
- }
-
- if(debug_lvl >= DEBUG_CONNECTIONS)
- syslog(LOG_INFO, _("Connected to %s port %hd"),
- c->hostname, c->port);
-cp
- return 0;
-}
-
-void setup_outgoing_connection(outgoing_t *outgoing)
-{
- connection_t *c;
- node_t *n;
- struct hostent *h;
-cp
- n = lookup_node(outgoing->name);
-
- if(n)
- if(n->connection)
- {
- if(debug_lvl >= DEBUG_CONNECTIONS)
- syslog(LOG_INFO, _("Already connected to %s"), outgoing->name);
- n->connection->outgoing = outgoing;
- return;
- }
-
- c = new_connection();
- c->name = xstrdup(outgoing->name);
-
- init_configuration(&c->config_tree);
- read_connection_config(c);
-
- if(!get_config_string(lookup_config(c->config_tree, "Address"), &c->hostname))
- {
- syslog(LOG_ERR, _("No address specified for %s"), c->name);
- free_connection(c);
- free(outgoing->name);
- free(outgoing);
- return;
- }
-
- if(!get_config_port(lookup_config(c->config_tree, "Port"), &c->port))
- c->port = 655;
-
- if(!(h = gethostbyname(c->hostname)))
- {
- syslog(LOG_ERR, _("Error looking up `%s': %m"), c->hostname);
- free_connection(c);
- retry_outgoing(outgoing);
- return;
- }
-
- c->address = ntohl(*((ipv4_t*)(h->h_addr_list[0])));
- c->hostname = hostlookup(htonl(c->address));
-
- if(setup_outgoing_socket(c) < 0)
- {
- syslog(LOG_ERR, _("Could not set up a meta connection to %s (%s)"),
- c->name, c->hostname);
- retry_outgoing(outgoing);
- return;
- }
-
- c->outgoing = outgoing;
- c->last_ping_time = time(NULL);
-
- connection_add(c);
-
- send_id(c);
-cp
-}
-
-int read_rsa_public_key(connection_t *c)
-{
- FILE *fp;
- char *fname;
- char *key;
-cp
- if(!c->rsa_key)
- c->rsa_key = RSA_new();
-
- /* First, check for simple PublicKey statement */
-
- if(get_config_string(lookup_config(c->config_tree, "PublicKey"), &key))
- {
- BN_hex2bn(&c->rsa_key->n, key);
- BN_hex2bn(&c->rsa_key->e, "FFFF");
- free(key);
- return 0;
- }
-
- /* Else, check for PublicKeyFile statement and read it */
-
- if(get_config_string(lookup_config(c->config_tree, "PublicKeyFile"), &fname))
- {
- if(is_safe_path(fname))
- {
- if((fp = fopen(fname, "r")) == NULL)
- {
- syslog(LOG_ERR, _("Error reading RSA public key file `%s': %m"),
- fname);
- free(fname);
- return -1;
- }
- free(fname);
- c->rsa_key = PEM_read_RSAPublicKey(fp, &c->rsa_key, NULL, NULL);
- fclose(fp);
- if(!c->rsa_key)
- {
- syslog(LOG_ERR, _("Reading RSA public key file `%s' failed: %m"),
- fname);
- return -1;
- }
- return 0;
- }
- else
- {
- free(fname);
- return -1;
- }
- }
-
- /* Else, check if a harnessed public key is in the config file */
-
- asprintf(&fname, "%s/hosts/%s", confbase, c->name);
- if((fp = fopen(fname, "r")))
- {
- c->rsa_key = PEM_read_RSAPublicKey(fp, &c->rsa_key, NULL, NULL);
- fclose(fp);
- }
-
- free(fname);
-
- if(c->rsa_key)
- return 0;
- else
- {
- syslog(LOG_ERR, _("No public key for %s specified!"), c->name);
- return -1;
- }
-}
-
-int read_rsa_private_key(void)
-{
- FILE *fp;
- char *fname, *key;
-cp
- if(get_config_string(lookup_config(config_tree, "PrivateKey"), &key))
- {
- myself->connection->rsa_key = RSA_new();
- BN_hex2bn(&myself->connection->rsa_key->d, key);
- BN_hex2bn(&myself->connection->rsa_key->e, "FFFF");
- free(key);
- return 0;
- }
-
- if(!get_config_string(lookup_config(config_tree, "PrivateKeyFile"), &fname))
- asprintf(&fname, "%s/rsa_key.priv", confbase);
-
- if(is_safe_path(fname))
- {
- if((fp = fopen(fname, "r")) == NULL)
- {
- syslog(LOG_ERR, _("Error reading RSA private key file `%s': %m"),
- fname);
- free(fname);
- return -1;
- }
- free(fname);
- myself->connection->rsa_key = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
- fclose(fp);
- if(!myself->connection->rsa_key)
- {
- syslog(LOG_ERR, _("Reading RSA private key file `%s' failed: %m"),
- fname);
- return -1;
- }
- return 0;
- }
-
- free(fname);
- return -1;
-}
-
-int check_rsa_key(RSA *rsa_key)
-{
- char *test1, *test2, *test3;
-cp
- if(rsa_key->p && rsa_key->q)
- {
- if(RSA_check_key(rsa_key) != 1)
- return -1;
- }
- else
- {
- test1 = xmalloc(RSA_size(rsa_key));
- test2 = xmalloc(RSA_size(rsa_key));
- test3 = xmalloc(RSA_size(rsa_key));
-
- if(RSA_public_encrypt(RSA_size(rsa_key), test1, test2, rsa_key, RSA_NO_PADDING) != RSA_size(rsa_key))
- return -1;
-
- if(RSA_private_decrypt(RSA_size(rsa_key), test2, test3, rsa_key, RSA_NO_PADDING) != RSA_size(rsa_key))
- return -1;
-
- if(memcmp(test1, test3, RSA_size(rsa_key)))
- return -1;
- }
-cp
- return 0;
-}
-
-/*
- Configure node_t myself and set up the local sockets (listen only)
-*/
-int setup_myself(void)
-{
- config_t *cfg;
- subnet_t *subnet;
- char *name, *mode, *cipher, *digest;
- int choice;
-cp
- myself = new_node();
- myself->connection = new_connection();
- init_configuration(&myself->connection->config_tree);
-
- asprintf(&myself->hostname, _("MYSELF"));
- asprintf(&myself->connection->hostname, _("MYSELF"));
-
- myself->connection->options = 0;
- myself->connection->protocol_version = PROT_CURRENT;
-
- if(!get_config_string(lookup_config(config_tree, "Name"), &name)) /* Not acceptable */
- {
- syslog(LOG_ERR, _("Name for tinc daemon required!"));
- return -1;
- }
-
- if(check_id(name))
- {
- syslog(LOG_ERR, _("Invalid name for myself!"));
- free(name);
- return -1;
- }
-
- myself->name = name;
- myself->connection->name = xstrdup(name);
-
-cp
- if(read_rsa_private_key())
- return -1;
-
- if(read_connection_config(myself->connection))
- {
- syslog(LOG_ERR, _("Cannot open host configuration file for myself!"));
- return -1;
- }
-
- if(read_rsa_public_key(myself->connection))
- return -1;
-cp
-
- if(check_rsa_key(myself->connection->rsa_key))
- {
- syslog(LOG_ERR, _("Invalid public/private keypair!"));
- return -1;
- }
-
- if(!get_config_port(lookup_config(myself->connection->config_tree, "Port"), &myself->port))
- myself->port = 655;
-
- myself->connection->port = myself->port;
-
-/* Read in all the subnets specified in the host configuration file */
-
- cfg = lookup_config(myself->connection->config_tree, "Subnet");
-
- while(cfg)
- {
- if(!get_config_subnet(cfg, &subnet))
- return -1;
-
- subnet_add(myself, subnet);
-
- cfg = lookup_config_next(myself->connection->config_tree, cfg);
- }
-
-cp
- /* Check some options */
-
- if(get_config_bool(lookup_config(config_tree, "IndirectData"), &choice))
- if(choice)
- myself->options |= OPTION_INDIRECT;
-
- if(get_config_bool(lookup_config(config_tree, "TCPOnly"), &choice))
- if(choice)
- myself->options |= OPTION_TCPONLY;
-
- if(get_config_bool(lookup_config(myself->connection->config_tree, "IndirectData"), &choice))
- if(choice)
- myself->options |= OPTION_INDIRECT;
-
- if(get_config_bool(lookup_config(myself->connection->config_tree, "TCPOnly"), &choice))
- if(choice)
- myself->options |= OPTION_TCPONLY;
-
- if(myself->options & OPTION_TCPONLY)
- myself->options |= OPTION_INDIRECT;
-
- if(get_config_string(lookup_config(config_tree, "Mode"), &mode))
- {
- if(!strcasecmp(mode, "router"))
- routing_mode = RMODE_ROUTER;
- else if (!strcasecmp(mode, "switch"))
- routing_mode = RMODE_SWITCH;
- else if (!strcasecmp(mode, "hub"))
- routing_mode = RMODE_HUB;
- else
- {
- syslog(LOG_ERR, _("Invalid routing mode!"));
- return -1;
- }
- }
- else
- routing_mode = RMODE_ROUTER;
-
-cp
- /* Open sockets */
-
- if((tcp_socket = setup_listen_socket(myself->port)) < 0)
- {
- syslog(LOG_ERR, _("Unable to set up a listening TCP socket!"));
- return -1;
- }
-
- if((udp_socket = setup_vpn_in_socket(myself->port)) < 0)
- {
- syslog(LOG_ERR, _("Unable to set up a listening UDP socket!"));
- return -1;
- }
-cp
- /* Generate packet encryption key */
-
- if(get_config_string(lookup_config(myself->connection->config_tree, "Cipher"), &cipher))
- {
- if(!strcasecmp(cipher, "none"))
- {
- myself->cipher = NULL;
- }
- else
- {
- if(!(myself->cipher = EVP_get_cipherbyname(cipher)))
- {
- syslog(LOG_ERR, _("Unrecognized cipher type!"));
- return -1;
- }
- }
- }
- else
- myself->cipher = EVP_bf_cbc();
-
- if(myself->cipher)
- myself->keylength = myself->cipher->key_len + myself->cipher->iv_len;
- else
- myself->keylength = 1;
-
- myself->key = (char *)xmalloc(myself->keylength);
- RAND_pseudo_bytes(myself->key, myself->keylength);
-
- if(!get_config_int(lookup_config(config_tree, "KeyExpire"), &keylifetime))
- keylifetime = 3600;
-
- keyexpires = time(NULL) + keylifetime;
-
- /* Check if we want to use message authentication codes... */
-
- if(get_config_string(lookup_config(myself->connection->config_tree, "Digest"), &digest))
- {
- if(!strcasecmp(digest, "none"))
- {
- myself->digest = NULL;
- }
- else
- {
- if(!(myself->digest = EVP_get_digestbyname(digest)))
- {
- syslog(LOG_ERR, _("Unrecognized digest type!"));
- return -1;
- }
- }
- }
- else
- myself->digest = EVP_sha1();
-
- if(get_config_int(lookup_config(myself->connection->config_tree, "MACLength"), &myself->maclength))
- {
- if(myself->digest)
- {
- if(myself->maclength > myself->digest->md_size)
- {
- syslog(LOG_ERR, _("MAC length exceeds size of digest!"));
- return -1;
- }
- else if (myself->maclength < 0)
- {
- syslog(LOG_ERR, _("Bogus MAC length!"));
- return -1;
- }
- }
- }
- else
- myself->maclength = 4;
-
- /* Compression */
-
- if(get_config_int(lookup_config(myself->connection->config_tree, "Compression"), &myself->compression))
- {
- if(myself->compression < 0 || myself->compression > 9)
- {
- syslog(LOG_ERR, _("Bogus compression level!"));
- return -1;
- }
- }
- else
- myself->compression = 0;
-cp
- /* Done */
-
- myself->nexthop = myself;
- myself->via = myself;
- myself->status.active = 1;
- node_add(myself);
-
- graph();
-
- syslog(LOG_NOTICE, _("Ready: listening on port %hd"), myself->port);
-cp
- return 0;
-}
-
-/*
- setup all initial network connections
-*/
-int setup_network_connections(void)
-{
-cp
- init_connections();
- init_subnets();
- init_nodes();
- init_edges();
- init_events();
-
- if(get_config_int(lookup_config(config_tree, "PingTimeout"), &pingtimeout))
- {
- if(pingtimeout < 1)
- {
- pingtimeout = 86400;
- }
- }
- else
- pingtimeout = 60;
-
- if(setup_device() < 0)
- return -1;
-
- /* Run tinc-up script to further initialize the tap interface */
- execute_script("tinc-up");
-
- if(setup_myself() < 0)
- return -1;
-
- try_outgoing_connections();
-cp
- return 0;
-}
-
-/*
- close all open network connections
-*/
-void close_network_connections(void)
-{
- avl_node_t *node, *next;
- connection_t *c;
-cp
- for(node = connection_tree->head; node; node = next)
- {
- next = node->next;
- c = (connection_t *)node->data;
- if(c->outgoing)
- free(c->outgoing->name), free(c->outgoing);
- terminate_connection(c, 0);
- }
-
- if(myself && myself->connection)
- terminate_connection(myself->connection, 0);
-
- close(udp_socket);
- close(tcp_socket);
-
- exit_events();
- exit_edges();
- exit_subnets();
- exit_nodes();
- exit_connections();
-
- execute_script("tinc-down");
-
- close_device();
-cp
- return;
-}
-
-/*
- handle an incoming tcp connect call and open
- a connection to it.
-*/
-connection_t *create_new_connection(int sfd)
-{
- connection_t *c;
- struct sockaddr_in ci;
- int len = sizeof(ci);
-cp
- c = new_connection();
-
- if(getpeername(sfd, (struct sockaddr *) &ci, (socklen_t *) &len) < 0)
- {
- syslog(LOG_ERR, _("System call `%s' failed: %m"),
- "getpeername");
- close(sfd);
- return NULL;
- }
+#include <utils.h>
+#include <xalloc.h>
+#include <avl_tree.h>
+#include <list.h>
- c->address = ntohl(ci.sin_addr.s_addr);
- c->hostname = hostlookup(ci.sin_addr.s_addr);
- c->port = htons(ci.sin_port);
- c->socket = sfd;
- c->last_ping_time = time(NULL);
+#include "conf.h"
+#include "connection.h"
+#include "meta.h"
+#include "net.h"
+#include "netutl.h"
+#include "process.h"
+#include "protocol.h"
+#include "subnet.h"
+#include "graph.h"
+#include "process.h"
+#include "route.h"
+#include "device.h"
+#include "event.h"
- if(debug_lvl >= DEBUG_CONNECTIONS)
- syslog(LOG_NOTICE, _("Connection from %s port %d"),
- c->hostname, c->port);
+#include "system.h"
- c->allow_request = ID;
-cp
- return c;
-}
+int do_prune = 0;
+int do_purge = 0;
+int sighup = 0;
+int sigalrm = 0;
/*
put all file descriptors in an fd_set array
cp
}
-/*
- receive incoming data from the listening
- udp socket and write it to the ethertap
- device after being decrypted
-*/
-void handle_incoming_vpn_data(void)
-{
- vpn_packet_t pkt;
- int x, l = sizeof(x);
- struct sockaddr_in from;
- socklen_t fromlen = sizeof(from);
- node_t *n;
-cp
- if(getsockopt(udp_socket, SOL_SOCKET, SO_ERROR, &x, &l) < 0)
- {
- syslog(LOG_ERR, _("This is a bug: %s:%d: %d:%m"),
- __FILE__, __LINE__, udp_socket);
- return;
- }
- if(x)
- {
- syslog(LOG_ERR, _("Incoming data socket error: %s"), strerror(x));
- return;
- }
-
- if((pkt.len = recvfrom(udp_socket, (char *)&pkt.seqno, MAXSIZE, 0, (struct sockaddr *)&from, &fromlen)) <= 0)
- {
- syslog(LOG_ERR, _("Receiving packet failed: %m"));
- return;
- }
-
- n = lookup_node_udp(ntohl(from.sin_addr.s_addr), ntohs(from.sin_port));
-
- if(!n)
- {
- syslog(LOG_WARNING, _("Received UDP packet on port %hd from unknown source %x:%hd"), myself->port, ntohl(from.sin_addr.s_addr), ntohs(from.sin_port));
- return;
- }
-
-/*
- if(n->connection)
- n->connection->last_ping_time = time(NULL);
-*/
- receive_udppacket(n, &pkt);
-cp
-}
-
/* Purge edges and subnets of unreachable nodes. Use carefully. */
void purge(void)
for(snode = n->subnet_tree->head; snode; snode = snext)
{
snext = snode->next;
- s = (subnet_t *)snode->data;
-
- for(cnode = connection_tree->head; cnode; cnode = cnode->next)
- {
- c = (connection_t *)cnode->data;
- if(c->status.active)
- send_del_subnet(c, s);
- }
-
- subnet_del(n, s);
+ s = (subnet_t *)snode->data;
+
+ for(cnode = connection_tree->head; cnode; cnode = cnode->next)
+ {
+ c = (connection_t *)cnode->data;
+ if(c->status.active)
+ send_del_subnet(c, s);
+ }
+
+ subnet_del(n, s);
}
-
+
for(enode = n->edge_tree->head; enode; enode = enext)
{
enext = enode->next;
- e = (edge_t *)enode->data;
-
- for(cnode = connection_tree->head; cnode; cnode = cnode->next)
- {
- c = (connection_t *)cnode->data;
- if(c->status.active)
- send_del_edge(c, e);
- }
-
- edge_del(e);
+ e = (edge_t *)enode->data;
+
+ for(cnode = connection_tree->head; cnode; cnode = cnode->next)
+ {
+ c = (connection_t *)cnode->data;
+ if(c->status.active)
+ send_del_edge(c, e);
+ }
+
+ edge_del(e);
}
node_del(n);
}
- }
+ }
cp
}
cp
if(c->status.remove)
return;
-
+
if(debug_lvl >= DEBUG_CONNECTIONS)
syslog(LOG_NOTICE, _("Closing connection with %s (%s)"),
c->name, c->hostname);
c->status.remove = 1;
-
+
if(c->socket)
close(c->socket);
}
/* Run MST and SSSP algorithms */
-
+
graph();
/* Check if this was our outgoing connection */
if(c->status.pinged)
{
if(debug_lvl >= DEBUG_PROTOCOL)
- syslog(LOG_INFO, _("%s (%s) didn't respond to PING"),
- c->name, c->hostname);
- c->status.timeout = 1;
- terminate_connection(c, 1);
+ syslog(LOG_INFO, _("%s (%s) didn't respond to PING"),
+ c->name, c->hostname);
+ c->status.timeout = 1;
+ terminate_connection(c, 1);
}
else
{
cp
}
-/*
- accept a new tcp connect and create a
- new connection
-*/
-int handle_new_meta_connection()
-{
- connection_t *new;
- struct sockaddr client;
- int fd, len = sizeof(client);
-cp
- if((fd = accept(tcp_socket, &client, &len)) < 0)
- {
- syslog(LOG_ERR, _("Accepting a new connection failed: %m"));
- return -1;
- }
-
- if(!(new = create_new_connection(fd)))
- {
- shutdown(fd, 2);
- close(fd);
- syslog(LOG_NOTICE, _("Closed attempted connection"));
- return 0;
- }
-
- connection_add(new);
-
- send_id(new);
-cp
- return 0;
-}
-
-void try_outgoing_connections(void)
-{
- static config_t *cfg = NULL;
- char *name;
- outgoing_t *outgoing;
-cp
- for(cfg = lookup_config(config_tree, "ConnectTo"); cfg; cfg = lookup_config_next(config_tree, cfg))
- {
- get_config_string(cfg, &name);
-
- if(check_id(name))
- {
- syslog(LOG_ERR, _("Invalid name for outgoing connection in %s line %d"), cfg->file, cfg->line);
- free(name);
- continue;
- }
-
- outgoing = xmalloc_and_zero(sizeof(*outgoing));
- outgoing->name = name;
- setup_outgoing_connection(outgoing);
- }
-}
-
/*
check all connections to see if anything
happened on their sockets
{
connection_t *c;
avl_node_t *node;
+ int result;
+ int len = sizeof(result);
+ vpn_packet_t packet;
cp
+ if(FD_ISSET(device_fd, f))
+ {
+ if(!read_packet(&packet))
+ route_outgoing(&packet);
+ }
+
if(FD_ISSET(udp_socket, f))
handle_incoming_vpn_data();
c = (connection_t *)node->data;
if(c->status.remove)
- return;
+ return;
if(FD_ISSET(c->socket, f))
- if(receive_meta(c) < 0)
- {
- terminate_connection(c, c->status.active);
- return;
- }
+ {
+ if(c->status.connecting)
+ {
+ c->status.connecting = 0;
+ getsockopt(c->socket, SOL_SOCKET, SO_ERROR, &result, &len);
+ if(!result)
+ finish_connecting(c);
+ else
+ {
+ if(debug_lvl >= DEBUG_CONNECTIONS)
+ syslog(LOG_DEBUG, _("Error while connecting to %s (%s): %s"), c->name, c->hostname, strerror(result));
+ close(c->socket);
+ do_outgoing_connection(c);
+ continue;
+ }
+ }
+ if(receive_meta(c) < 0)
+ {
+ terminate_connection(c, c->status.active);
+ return;
+ }
+ }
}
if(FD_ISSET(tcp_socket, f))
c = (connection_t *)node->data;
if(c->status.remove)
- connection_del(c);
+ connection_del(c);
}
-
+
if(!connection_tree->head)
purge();
cp
time_t last_ping_check;
int t;
event_t *event;
- vpn_packet_t packet;
cp
last_ping_check = time(NULL);
tv.tv_sec = 1 + (rand() & 7); /* Approx. 5 seconds, randomized to prevent global synchronisation effects */
tv.tv_usec = 0;
- if(do_prune)
- {
- prune_connections();
- do_prune = 0;
- }
-
build_fdset(&fset);
if((r = select(FD_SETSIZE, &fset, NULL, NULL, &tv)) < 0)
{
- if(errno != EINTR) /* because of a signal */
+ if(errno != EINTR) /* because of a signal */
{
- syslog(LOG_ERR, _("Error while waiting for input: %m"));
+ syslog(LOG_ERR, _("Error while waiting for input: %s"), strerror(errno));
return;
}
}
- if(sighup)
- {
- syslog(LOG_INFO, _("Rereading configuration file and restarting in 5 seconds"));
- sighup = 0;
- close_network_connections();
- exit_configuration(&config_tree);
-
- if(read_server_config())
- {
- syslog(LOG_ERR, _("Unable to reread configuration file, exiting"));
- exit(1);
- }
-
- sleep(5);
-
- if(setup_network_connections())
- return;
+ if(r > 0)
+ check_network_activity(&fset);
- continue;
+ if(do_prune)
+ {
+ prune_connections();
+ do_prune = 0;
}
- if(do_purge)
+ if(do_purge)
{
- purge();
- do_purge = 0;
- }
+ purge();
+ do_purge = 0;
+ }
t = time(NULL);
/* Let's check if everybody is still alive */
if(last_ping_check + pingtimeout < t)
- {
- check_dead_connections();
+ {
+ check_dead_connections();
last_ping_check = time(NULL);
/* Should we regenerate our key? */
send_key_changed(myself->connection, myself);
keyexpires = time(NULL) + keylifetime;
}
- }
+ }
+
+
+ while((event = get_expired_event()))
+ {
+ event->handler(event->data);
+ free(event);
+ }
if(sigalrm)
{
syslog(LOG_INFO, _("Flushing event queue"));
- while(event_tree->head)
- {
- event = (event_t *)event_tree->head->data;
- event->handler(event->data);
- event_del(event);
- }
- sigalrm = 0;
+ while(event_tree->head)
+ {
+ event = (event_t *)event_tree->head->data;
+ event->handler(event->data);
+ event_del(event);
+ }
+ sigalrm = 0;
}
- while((event = get_expired_event()))
- {
- event->handler(event->data);
- free(event);
- }
-
- if(r > 0)
+ if(sighup)
{
- check_network_activity(&fset);
+ syslog(LOG_INFO, _("Rereading configuration file and restarting in 5 seconds"));
+ sighup = 0;
+ close_network_connections();
+ exit_configuration(&config_tree);
- /* local tap data */
- if(FD_ISSET(device_fd, &fset))
+ if(read_server_config())
{
- if(!read_packet(&packet))
- route_outgoing(&packet);
+ syslog(LOG_ERR, _("Unable to reread configuration file, exiting"));
+ exit(1);
}
+
+ sleep(5);
+
+ if(setup_network_connections())
+ return;
+
+ continue;
}
}
cp
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: net.h,v 1.9.4.38 2002/02/10 21:57:54 guus Exp $
+ $Id: net.h,v 1.9.4.39 2002/02/18 16:25:16 guus Exp $
*/
#ifndef __TINC_NET_H__
#define __TINC_NET_H__
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
#include <sys/time.h>
#include "config.h"
unsigned char x[6];
} mac_t;
-typedef unsigned long ipv4_t;
+typedef struct ipv4_t
+{
+ unsigned char x[4];
+} ipv4_t;
typedef struct ip_mask_t {
ipv4_t address;
typedef short length_t;
+typedef union {
+ struct sockaddr sa;
+ struct sockaddr_in in;
+ struct sockaddr_in6 in6;
+} sockaddr_t;
+
+#define SA_PORT(s) ((s.sa.sa_family==AF_INET)?s.in.sin_port:(s.sa.sa_family==AF_INET6)?s.in6.sin6_port:0)
+
typedef struct vpn_packet_t {
length_t len; /* the actual number of bytes in the `data' field */
unsigned int seqno; /* 32 bits sequence number (network byte order of course) */
typedef struct outgoing_t {
char *name;
int timeout;
+ struct config_t *cfg;
+ struct addrinfo *ai;
+ struct addrinfo *aip;
} outgoing_t;
extern int maxtimeout;
extern int seconds_till_retry;
+extern int addressfamily;
extern char *request_name[];
extern char *status_text[];
#include "connection.h" /* Yes, very strange placement indeed, but otherwise the typedefs get all tangled up */
+extern int tcp_socket;
+extern int udp_socket;
+extern int keyexpires;
+extern int keylifetime;
+extern int do_prune;
+extern int do_purge;
+extern char *myport;
+
+extern void retry_outgoing(outgoing_t *);
+extern void handle_incoming_vpn_data(void);
+extern void finish_connecting(connection_t *);
+extern void do_outgoing_connection(connection_t *);
+extern int handle_new_meta_connection(void);
+extern int setup_listen_socket(sockaddr_t *);
+extern int setup_vpn_in_socket(sockaddr_t *);
extern void send_packet(struct node_t *, vpn_packet_t *);
extern void receive_packet(struct node_t *, vpn_packet_t *);
extern void receive_tcppacket(struct connection_t *, char *, int);
--- /dev/null
+/*
+ net_packet.c -- Handles in- and outgoing VPN packets
+ Copyright (C) 1998-2002 Ivo Timmermans <itimmermans@bigfoot.com>,
+ 2000-2002 Guus Sliepen <guus@sliepen.warande.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id: net_packet.c,v 1.1.2.1 2002/02/18 16:25:16 guus Exp $
+*/
+
+#include "config.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#ifdef HAVE_LINUX
+ #include <netinet/ip.h>
+ #include <netinet/tcp.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+/* SunOS really wants sys/socket.h BEFORE net/if.h,
+ and FreeBSD wants these lines below the rest. */
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#include <openssl/rand.h>
+#include <openssl/evp.h>
+#include <openssl/pem.h>
+#include <openssl/hmac.h>
+
+#ifndef HAVE_RAND_PSEUDO_BYTES
+#define RAND_pseudo_bytes RAND_bytes
+#endif
+
+#include <zlib.h>
+
+#include <utils.h>
+#include <xalloc.h>
+#include <avl_tree.h>
+#include <list.h>
+
+#include "conf.h"
+#include "connection.h"
+#include "meta.h"
+#include "net.h"
+#include "netutl.h"
+#include "process.h"
+#include "protocol.h"
+#include "subnet.h"
+#include "graph.h"
+#include "process.h"
+#include "route.h"
+#include "device.h"
+#include "event.h"
+
+#include "system.h"
+
+int keylifetime = 0;
+int keyexpires = 0;
+
+#define MAX_SEQNO 1073741824
+
+/* VPN packet I/O */
+
+void receive_udppacket(node_t *n, vpn_packet_t *inpkt)
+{
+ vpn_packet_t pkt1, pkt2;
+ vpn_packet_t *pkt[] = {&pkt1, &pkt2, &pkt1, &pkt2};
+ int nextpkt = 0;
+ vpn_packet_t *outpkt = pkt[0];
+ int outlen, outpad;
+ long int complen = MTU + 12;
+ EVP_CIPHER_CTX ctx;
+ char hmac[EVP_MAX_MD_SIZE];
+cp
+ /* Check the message authentication code */
+
+ if(myself->digest && myself->maclength)
+ {
+ inpkt->len -= myself->maclength;
+ HMAC(myself->digest, myself->key, myself->keylength, (char *)&inpkt->seqno, inpkt->len, hmac, NULL);
+ if(memcmp(hmac, (char *)&inpkt->seqno + inpkt->len, myself->maclength))
+ {
+ syslog(LOG_DEBUG, _("Got unauthenticated packet from %s (%s)"), n->name, n->hostname);
+ return;
+ }
+ }
+
+ /* Decrypt the packet */
+
+ if(myself->cipher)
+ {
+ outpkt = pkt[nextpkt++];
+
+ EVP_DecryptInit(&ctx, myself->cipher, myself->key, myself->key + myself->cipher->key_len);
+ EVP_DecryptUpdate(&ctx, (char *)&outpkt->seqno, &outlen, (char *)&inpkt->seqno, inpkt->len);
+ EVP_DecryptFinal(&ctx, (char *)&outpkt->seqno + outlen, &outpad);
+
+ outpkt->len = outlen + outpad;
+ inpkt = outpkt;
+ }
+
+ /* Check the sequence number */
+
+ inpkt->len -= sizeof(inpkt->seqno);
+ inpkt->seqno = ntohl(inpkt->seqno);
+
+ if(inpkt->seqno <= n->received_seqno)
+ {
+ syslog(LOG_DEBUG, _("Got late or replayed packet from %s (%s), seqno %d"), n->name, n->hostname, inpkt->seqno);
+ return;
+ }
+
+ n->received_seqno = inpkt->seqno;
+
+ if(n->received_seqno > MAX_SEQNO)
+ keyexpires = 0;
+
+ /* Decompress the packet */
+
+ if(myself->compression)
+ {
+ outpkt = pkt[nextpkt++];
+
+ if(uncompress(outpkt->data, &complen, inpkt->data, inpkt->len) != Z_OK)
+ {
+ syslog(LOG_ERR, _("Error while uncompressing packet from %s (%s)"), n->name, n->hostname);
+ return;
+ }
+
+ outpkt->len = complen;
+ inpkt = outpkt;
+ }
+
+ receive_packet(n, inpkt);
+cp
+}
+
+void receive_tcppacket(connection_t *c, char *buffer, int len)
+{
+ vpn_packet_t outpkt;
+cp
+ outpkt.len = len;
+ memcpy(outpkt.data, buffer, len);
+
+ receive_packet(c->node, &outpkt);
+cp
+}
+
+void receive_packet(node_t *n, vpn_packet_t *packet)
+{
+cp
+ if(debug_lvl >= DEBUG_TRAFFIC)
+ syslog(LOG_DEBUG, _("Received packet of %d bytes from %s (%s)"), packet->len, n->name, n->hostname);
+
+ route_incoming(n, packet);
+cp
+}
+
+void send_udppacket(node_t *n, vpn_packet_t *inpkt)
+{
+ vpn_packet_t pkt1, pkt2;
+ vpn_packet_t *pkt[] = {&pkt1, &pkt2, &pkt1, &pkt2};
+ int nextpkt = 0;
+ vpn_packet_t *outpkt;
+ int outlen, outpad;
+ long int complen = MTU + 12;
+ EVP_CIPHER_CTX ctx;
+ vpn_packet_t *copy;
+cp
+ if(!n->status.validkey)
+ {
+ if(debug_lvl >= DEBUG_TRAFFIC)
+ syslog(LOG_INFO, _("No valid key known yet for %s (%s), queueing packet"),
+ n->name, n->hostname);
+
+ /* Since packet is on the stack of handle_tap_input(),
+ we have to make a copy of it first. */
+
+ copy = xmalloc(sizeof(vpn_packet_t));
+ memcpy(copy, inpkt, sizeof(vpn_packet_t));
+
+ list_insert_tail(n->queue, copy);
+
+ if(!n->status.waitingforkey)
+ send_req_key(n->nexthop->connection, myself, n);
+
+ return;
+ }
+
+ /* Compress the packet */
+
+ if(n->compression)
+ {
+ outpkt = pkt[nextpkt++];
+
+ if(compress2(outpkt->data, &complen, inpkt->data, inpkt->len, n->compression) != Z_OK)
+ {
+ syslog(LOG_ERR, _("Error while compressing packet to %s (%s)"), n->name, n->hostname);
+ return;
+ }
+
+ outpkt->len = complen;
+ inpkt = outpkt;
+ }
+
+ /* Add sequence number */
+
+ inpkt->seqno = htonl(++(n->sent_seqno));
+ inpkt->len += sizeof(inpkt->seqno);
+
+ /* Encrypt the packet */
+
+ if(n->cipher)
+ {
+ outpkt = pkt[nextpkt++];
+
+ EVP_EncryptInit(&ctx, n->cipher, n->key, n->key + n->cipher->key_len);
+ EVP_EncryptUpdate(&ctx, (char *)&outpkt->seqno, &outlen, (char *)&inpkt->seqno, inpkt->len);
+ EVP_EncryptFinal(&ctx, (char *)&outpkt->seqno + outlen, &outpad);
+
+ outpkt->len = outlen + outpad;
+ inpkt = outpkt;
+ }
+
+ /* Add the message authentication code */
+
+ if(n->digest && n->maclength)
+ {
+ HMAC(n->digest, n->key, n->keylength, (char *)&inpkt->seqno, inpkt->len, (char *)&inpkt->seqno + inpkt->len, &outlen);
+ inpkt->len += n->maclength;
+ }
+
+ /* Send the packet */
+
+ if((sendto(udp_socket, (char *)&inpkt->seqno, inpkt->len, 0, &(n->address.sa), sizeof(sockaddr_t))) < 0)
+ {
+ syslog(LOG_ERR, _("Error sending packet to %s (%s): %s"),
+ n->name, n->hostname, strerror(errno));
+ return;
+ }
+cp
+}
+
+/*
+ send a packet to the given vpn ip.
+*/
+void send_packet(node_t *n, vpn_packet_t *packet)
+{
+ node_t *via;
+cp
+ if(debug_lvl >= DEBUG_TRAFFIC)
+ syslog(LOG_ERR, _("Sending packet of %d bytes to %s (%s)"),
+ packet->len, n->name, n->hostname);
+
+ if(n == myself)
+ {
+ if(debug_lvl >= DEBUG_TRAFFIC)
+ {
+ syslog(LOG_NOTICE, _("Packet is looping back to us!"));
+ }
+
+ return;
+ }
+
+ if(!n->status.reachable)
+ {
+ if(debug_lvl >= DEBUG_TRAFFIC)
+ syslog(LOG_INFO, _("Node %s (%s) is not reachable"),
+ n->name, n->hostname);
+ return;
+ }
+
+ via = (n->via == myself)?n->nexthop:n->via;
+
+ if(via != n && debug_lvl >= DEBUG_TRAFFIC)
+ syslog(LOG_ERR, _("Sending packet to %s via %s (%s)"),
+ n->name, via->name, n->via->hostname);
+
+ if((myself->options | via->options) & OPTION_TCPONLY)
+ {
+ if(send_tcppacket(via->connection, packet))
+ terminate_connection(via->connection, 1);
+ }
+ else
+ send_udppacket(via, packet);
+}
+
+/* Broadcast a packet using the minimum spanning tree */
+
+void broadcast_packet(node_t *from, vpn_packet_t *packet)
+{
+ avl_node_t *node;
+ connection_t *c;
+cp
+ if(debug_lvl >= DEBUG_TRAFFIC)
+ syslog(LOG_INFO, _("Broadcasting packet of %d bytes from %s (%s)"),
+ packet->len, from->name, from->hostname);
+
+ for(node = connection_tree->head; node; node = node->next)
+ {
+ c = (connection_t *)node->data;
+ if(c->status.active && c->status.mst && c != from->nexthop->connection)
+ send_packet(c->node, packet);
+ }
+cp
+}
+
+void flush_queue(node_t *n)
+{
+ list_node_t *node, *next;
+cp
+ if(debug_lvl >= DEBUG_TRAFFIC)
+ syslog(LOG_INFO, _("Flushing queue for %s (%s)"), n->name, n->hostname);
+
+ for(node = n->queue->head; node; node = next)
+ {
+ next = node->next;
+ send_udppacket(n, (vpn_packet_t *)node->data);
+ list_delete_node(n->queue, node);
+ }
+cp
+}
+
+void handle_incoming_vpn_data(void)
+{
+ vpn_packet_t pkt;
+ int x, l = sizeof(x);
+ char *hostname;
+ sockaddr_t from;
+ socklen_t fromlen = sizeof(from);
+ node_t *n;
+cp
+ if(getsockopt(udp_socket, SOL_SOCKET, SO_ERROR, &x, &l) < 0)
+ {
+ syslog(LOG_ERR, _("This is a bug: %s:%d: %d:%s"),
+ __FILE__, __LINE__, udp_socket, strerror(errno));
+ return;
+ }
+ if(x)
+ {
+ syslog(LOG_ERR, _("Incoming data socket error: %s"), strerror(x));
+ return;
+ }
+
+ if((pkt.len = recvfrom(udp_socket, (char *)&pkt.seqno, MAXSIZE, 0, &from.sa, &fromlen)) <= 0)
+ {
+ syslog(LOG_ERR, _("Receiving packet failed: %s"), strerror(errno));
+ return;
+ }
+
+ n = lookup_node_udp(&from);
+
+ if(!n)
+ {
+ hostname = sockaddr2hostname(&from);
+ syslog(LOG_WARNING, _("Received UDP packet from unknown source %s"), hostname);
+ free(hostname);
+ return;
+ }
+
+/*
+ if(n->connection)
+ n->connection->last_ping_time = time(NULL);
+*/
+ receive_udppacket(n, &pkt);
+cp
+}
+
--- /dev/null
+/*
+ net_setup.c -- Setup.
+ Copyright (C) 1998-2002 Ivo Timmermans <itimmermans@bigfoot.com>,
+ 2000-2002 Guus Sliepen <guus@sliepen.warande.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id: net_setup.c,v 1.1.2.1 2002/02/18 16:25:16 guus Exp $
+*/
+
+#include "config.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#ifdef HAVE_LINUX
+ #include <netinet/ip.h>
+ #include <netinet/tcp.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+/* SunOS really wants sys/socket.h BEFORE net/if.h,
+ and FreeBSD wants these lines below the rest. */
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#include <openssl/pem.h>
+#include <openssl/rsa.h>
+#include <openssl/rand.h>
+
+#include <utils.h>
+#include <xalloc.h>
+#include <avl_tree.h>
+#include <list.h>
+
+#include "conf.h"
+#include "connection.h"
+#include "meta.h"
+#include "net.h"
+#include "netutl.h"
+#include "process.h"
+#include "protocol.h"
+#include "subnet.h"
+#include "graph.h"
+#include "process.h"
+#include "route.h"
+#include "device.h"
+#include "event.h"
+
+#include "system.h"
+
+char *myport;
+
+int read_rsa_public_key(connection_t *c)
+{
+ FILE *fp;
+ char *fname;
+ char *key;
+cp
+ if(!c->rsa_key)
+ c->rsa_key = RSA_new();
+
+ /* First, check for simple PublicKey statement */
+
+ if(get_config_string(lookup_config(c->config_tree, "PublicKey"), &key))
+ {
+ BN_hex2bn(&c->rsa_key->n, key);
+ BN_hex2bn(&c->rsa_key->e, "FFFF");
+ free(key);
+ return 0;
+ }
+
+ /* Else, check for PublicKeyFile statement and read it */
+
+ if(get_config_string(lookup_config(c->config_tree, "PublicKeyFile"), &fname))
+ {
+ if(is_safe_path(fname))
+ {
+ if((fp = fopen(fname, "r")) == NULL)
+ {
+ syslog(LOG_ERR, _("Error reading RSA public key file `%s': %s"),
+ fname, strerror(errno));
+ free(fname);
+ return -1;
+ }
+ free(fname);
+ c->rsa_key = PEM_read_RSAPublicKey(fp, &c->rsa_key, NULL, NULL);
+ fclose(fp);
+ if(!c->rsa_key)
+ {
+ syslog(LOG_ERR, _("Reading RSA public key file `%s' failed: %s"),
+ fname, strerror(errno));
+ return -1;
+ }
+ return 0;
+ }
+ else
+ {
+ free(fname);
+ return -1;
+ }
+ }
+
+ /* Else, check if a harnessed public key is in the config file */
+
+ asprintf(&fname, "%s/hosts/%s", confbase, c->name);
+ if((fp = fopen(fname, "r")))
+ {
+ c->rsa_key = PEM_read_RSAPublicKey(fp, &c->rsa_key, NULL, NULL);
+ fclose(fp);
+ }
+
+ free(fname);
+
+ if(c->rsa_key)
+ return 0;
+ else
+ {
+ syslog(LOG_ERR, _("No public key for %s specified!"), c->name);
+ return -1;
+ }
+}
+
+int read_rsa_private_key(void)
+{
+ FILE *fp;
+ char *fname, *key;
+cp
+ if(get_config_string(lookup_config(config_tree, "PrivateKey"), &key))
+ {
+ myself->connection->rsa_key = RSA_new();
+ BN_hex2bn(&myself->connection->rsa_key->d, key);
+ BN_hex2bn(&myself->connection->rsa_key->e, "FFFF");
+ free(key);
+ return 0;
+ }
+
+ if(!get_config_string(lookup_config(config_tree, "PrivateKeyFile"), &fname))
+ asprintf(&fname, "%s/rsa_key.priv", confbase);
+
+ if(is_safe_path(fname))
+ {
+ if((fp = fopen(fname, "r")) == NULL)
+ {
+ syslog(LOG_ERR, _("Error reading RSA private key file `%s': %s"),
+ fname, strerror(errno));
+ free(fname);
+ return -1;
+ }
+ free(fname);
+ myself->connection->rsa_key = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
+ fclose(fp);
+ if(!myself->connection->rsa_key)
+ {
+ syslog(LOG_ERR, _("Reading RSA private key file `%s' failed: %s"),
+ fname, strerror(errno));
+ return -1;
+ }
+ return 0;
+ }
+
+ free(fname);
+ return -1;
+}
+
+int check_rsa_key(RSA *rsa_key)
+{
+ char *test1, *test2, *test3;
+cp
+ if(rsa_key->p && rsa_key->q)
+ {
+ if(RSA_check_key(rsa_key) != 1)
+ return -1;
+ }
+ else
+ {
+ test1 = xmalloc(RSA_size(rsa_key));
+ test2 = xmalloc(RSA_size(rsa_key));
+ test3 = xmalloc(RSA_size(rsa_key));
+
+ if(RSA_public_encrypt(RSA_size(rsa_key), test1, test2, rsa_key, RSA_NO_PADDING) != RSA_size(rsa_key))
+ return -1;
+
+ if(RSA_private_decrypt(RSA_size(rsa_key), test2, test3, rsa_key, RSA_NO_PADDING) != RSA_size(rsa_key))
+ return -1;
+
+ if(memcmp(test1, test3, RSA_size(rsa_key)))
+ return -1;
+ }
+cp
+ return 0;
+}
+
+/*
+ Configure node_t myself and set up the local sockets (listen only)
+*/
+int setup_myself(void)
+{
+ config_t *cfg;
+ subnet_t *subnet;
+ char *name, *mode, *afname, *cipher, *digest;
+ struct addrinfo hint, *ai;
+ int choice;
+cp
+ myself = new_node();
+ myself->connection = new_connection();
+ init_configuration(&myself->connection->config_tree);
+
+ asprintf(&myself->hostname, _("MYSELF"));
+ asprintf(&myself->connection->hostname, _("MYSELF"));
+
+ myself->connection->options = 0;
+ myself->connection->protocol_version = PROT_CURRENT;
+
+ if(!get_config_string(lookup_config(config_tree, "Name"), &name)) /* Not acceptable */
+ {
+ syslog(LOG_ERR, _("Name for tinc daemon required!"));
+ return -1;
+ }
+
+ if(check_id(name))
+ {
+ syslog(LOG_ERR, _("Invalid name for myself!"));
+ free(name);
+ return -1;
+ }
+
+ myself->name = name;
+ myself->connection->name = xstrdup(name);
+
+cp
+ if(read_rsa_private_key())
+ return -1;
+
+ if(read_connection_config(myself->connection))
+ {
+ syslog(LOG_ERR, _("Cannot open host configuration file for myself!"));
+ return -1;
+ }
+
+ if(read_rsa_public_key(myself->connection))
+ return -1;
+cp
+
+ if(check_rsa_key(myself->connection->rsa_key))
+ {
+ syslog(LOG_ERR, _("Invalid public/private keypair!"));
+ return -1;
+ }
+
+ if(!get_config_string(lookup_config(myself->connection->config_tree, "Port"), &myport))
+ asprintf(&myport, "655");
+
+/* Read in all the subnets specified in the host configuration file */
+
+ cfg = lookup_config(myself->connection->config_tree, "Subnet");
+
+ while(cfg)
+ {
+ if(!get_config_subnet(cfg, &subnet))
+ return -1;
+
+ subnet_add(myself, subnet);
+
+ cfg = lookup_config_next(myself->connection->config_tree, cfg);
+ }
+
+cp
+ /* Check some options */
+
+ if(get_config_bool(lookup_config(config_tree, "IndirectData"), &choice))
+ if(choice)
+ myself->options |= OPTION_INDIRECT;
+
+ if(get_config_bool(lookup_config(config_tree, "TCPOnly"), &choice))
+ if(choice)
+ myself->options |= OPTION_TCPONLY;
+
+ if(get_config_bool(lookup_config(myself->connection->config_tree, "IndirectData"), &choice))
+ if(choice)
+ myself->options |= OPTION_INDIRECT;
+
+ if(get_config_bool(lookup_config(myself->connection->config_tree, "TCPOnly"), &choice))
+ if(choice)
+ myself->options |= OPTION_TCPONLY;
+
+ if(myself->options & OPTION_TCPONLY)
+ myself->options |= OPTION_INDIRECT;
+
+ if(get_config_string(lookup_config(config_tree, "Mode"), &mode))
+ {
+ if(!strcasecmp(mode, "router"))
+ routing_mode = RMODE_ROUTER;
+ else if (!strcasecmp(mode, "switch"))
+ routing_mode = RMODE_SWITCH;
+ else if (!strcasecmp(mode, "hub"))
+ routing_mode = RMODE_HUB;
+ else
+ {
+ syslog(LOG_ERR, _("Invalid routing mode!"));
+ return -1;
+ }
+ free(mode);
+ }
+ else
+ routing_mode = RMODE_ROUTER;
+
+ if(get_config_int(lookup_config(myself->connection->config_tree, "MaxTimeout"), &maxtimeout))
+ {
+ if(maxtimeout <= 0)
+ {
+ syslog(LOG_ERR, _("Bogus maximum timeout!"));
+ return -1;
+ }
+ }
+ else
+ maxtimeout = 900;
+
+ if(get_config_string(lookup_config(config_tree, "AddressFamily"), &afname))
+ {
+ if(!strcasecmp(afname, "IPv4"))
+ addressfamily = AF_INET;
+ else if (!strcasecmp(afname, "IPv6"))
+ addressfamily = AF_INET6;
+ else if (!strcasecmp(afname, "any"))
+ addressfamily = AF_UNSPEC;
+ else
+ {
+ syslog(LOG_ERR, _("Invalid address family!"));
+ return -1;
+ }
+ free(afname);
+ }
+ else
+ addressfamily = AF_INET;
+
+ get_config_bool(lookup_config(config_tree, "Hostnames"), &hostnames);
+cp
+ /* Generate packet encryption key */
+
+ if(get_config_string(lookup_config(myself->connection->config_tree, "Cipher"), &cipher))
+ {
+ if(!strcasecmp(cipher, "none"))
+ {
+ myself->cipher = NULL;
+ }
+ else
+ {
+ if(!(myself->cipher = EVP_get_cipherbyname(cipher)))
+ {
+ syslog(LOG_ERR, _("Unrecognized cipher type!"));
+ return -1;
+ }
+ }
+ }
+ else
+ myself->cipher = EVP_bf_cbc();
+
+ if(myself->cipher)
+ myself->keylength = myself->cipher->key_len + myself->cipher->iv_len;
+ else
+ myself->keylength = 1;
+
+ myself->key = (char *)xmalloc(myself->keylength);
+ RAND_pseudo_bytes(myself->key, myself->keylength);
+
+ if(!get_config_int(lookup_config(config_tree, "KeyExpire"), &keylifetime))
+ keylifetime = 3600;
+
+ keyexpires = time(NULL) + keylifetime;
+
+ /* Check if we want to use message authentication codes... */
+
+ if(get_config_string(lookup_config(myself->connection->config_tree, "Digest"), &digest))
+ {
+ if(!strcasecmp(digest, "none"))
+ {
+ myself->digest = NULL;
+ }
+ else
+ {
+ if(!(myself->digest = EVP_get_digestbyname(digest)))
+ {
+ syslog(LOG_ERR, _("Unrecognized digest type!"));
+ return -1;
+ }
+ }
+ }
+ else
+ myself->digest = EVP_sha1();
+
+ if(get_config_int(lookup_config(myself->connection->config_tree, "MACLength"), &myself->maclength))
+ {
+ if(myself->digest)
+ {
+ if(myself->maclength > myself->digest->md_size)
+ {
+ syslog(LOG_ERR, _("MAC length exceeds size of digest!"));
+ return -1;
+ }
+ else if (myself->maclength < 0)
+ {
+ syslog(LOG_ERR, _("Bogus MAC length!"));
+ return -1;
+ }
+ }
+ }
+ else
+ myself->maclength = 4;
+
+ /* Compression */
+
+ if(get_config_int(lookup_config(myself->connection->config_tree, "Compression"), &myself->compression))
+ {
+ if(myself->compression < 0 || myself->compression > 9)
+ {
+ syslog(LOG_ERR, _("Bogus compression level!"));
+ return -1;
+ }
+ }
+ else
+ myself->compression = 0;
+cp
+ /* Done */
+
+ myself->nexthop = myself;
+ myself->via = myself;
+ myself->status.active = 1;
+ node_add(myself);
+
+ graph();
+
+cp
+ /* Open sockets */
+
+ hint.ai_family = (addressfamily == AF_UNSPEC)?AF_INET6:addressfamily;
+ hint.ai_socktype = SOCK_STREAM;
+ hint.ai_protocol = IPPROTO_TCP;
+ hint.ai_flags = AI_PASSIVE;
+
+ if(getaddrinfo(NULL, myport, &hint, &ai) || !ai)
+ {
+ syslog(LOG_ERR, _("System call `%s' failed: %s"), "getaddrinfo", strerror(errno));
+ return -1;
+ }
+
+ if((tcp_socket = setup_listen_socket((sockaddr_t *)ai->ai_addr)) < 0)
+ {
+ syslog(LOG_ERR, _("Unable to set up a listening TCP socket!"));
+ return -1;
+ }
+
+ if((udp_socket = setup_vpn_in_socket((sockaddr_t *)ai->ai_addr)) < 0)
+ {
+ syslog(LOG_ERR, _("Unable to set up a listening UDP socket!"));
+ return -1;
+ }
+
+ freeaddrinfo(ai);
+
+ syslog(LOG_NOTICE, _("Ready: listening on port %s"), myport);
+cp
+ return 0;
+}
+
+/*
+ setup all initial network connections
+*/
+int setup_network_connections(void)
+{
+cp
+ init_connections();
+ init_subnets();
+ init_nodes();
+ init_edges();
+ init_events();
+
+ if(get_config_int(lookup_config(config_tree, "PingTimeout"), &pingtimeout))
+ {
+ if(pingtimeout < 1)
+ {
+ pingtimeout = 86400;
+ }
+ }
+ else
+ pingtimeout = 60;
+
+ if(setup_device() < 0)
+ return -1;
+
+ /* Run tinc-up script to further initialize the tap interface */
+ execute_script("tinc-up");
+
+ if(setup_myself() < 0)
+ return -1;
+
+ try_outgoing_connections();
+cp
+ return 0;
+}
+
+/*
+ close all open network connections
+*/
+void close_network_connections(void)
+{
+ avl_node_t *node, *next;
+ connection_t *c;
+cp
+ for(node = connection_tree->head; node; node = next)
+ {
+ next = node->next;
+ c = (connection_t *)node->data;
+ if(c->outgoing)
+ free(c->outgoing->name), free(c->outgoing);
+ terminate_connection(c, 0);
+ }
+
+ if(myself && myself->connection)
+ terminate_connection(myself->connection, 0);
+
+ close(udp_socket);
+ close(tcp_socket);
+
+ exit_events();
+ exit_edges();
+ exit_subnets();
+ exit_nodes();
+ exit_connections();
+
+ execute_script("tinc-down");
+
+ close_device();
+cp
+ return;
+}
--- /dev/null
+/*
+ net_socket.c -- Handle various kinds of sockets.
+ Copyright (C) 1998-2002 Ivo Timmermans <itimmermans@bigfoot.com>,
+ 2000-2002 Guus Sliepen <guus@sliepen.warande.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id: net_socket.c,v 1.1.2.1 2002/02/18 16:25:16 guus Exp $
+*/
+
+#include "config.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#ifdef HAVE_LINUX
+ #include <netinet/ip.h>
+ #include <netinet/tcp.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+/* SunOS really wants sys/socket.h BEFORE net/if.h,
+ and FreeBSD wants these lines below the rest. */
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#include <utils.h>
+#include <xalloc.h>
+#include <avl_tree.h>
+#include <list.h>
+
+#include "conf.h"
+#include "connection.h"
+#include "meta.h"
+#include "net.h"
+#include "netutl.h"
+#include "process.h"
+#include "protocol.h"
+#include "subnet.h"
+#include "graph.h"
+#include "process.h"
+#include "route.h"
+#include "device.h"
+#include "event.h"
+
+#include "system.h"
+
+int addressfamily = AF_INET;
+int maxtimeout = 900;
+int seconds_till_retry = 5;
+
+int tcp_socket = -1;
+int udp_socket = -1;
+/* Setup sockets */
+
+int setup_listen_socket(sockaddr_t *sa)
+{
+ int nfd, flags;
+ char *addrstr;
+ int option;
+#ifdef HAVE_LINUX
+ char *interface;
+#endif
+cp
+ if((nfd = socket(sa->sa.sa_family, SOCK_STREAM, IPPROTO_TCP)) < 0)
+ {
+ syslog(LOG_ERR, _("Creating metasocket failed: %s"), strerror(errno));
+ return -1;
+ }
+
+ flags = fcntl(nfd, F_GETFL);
+ if(fcntl(nfd, F_SETFL, flags | O_NONBLOCK) < 0)
+ {
+ close(nfd);
+ syslog(LOG_ERR, _("System call `%s' failed: %s"), "fcntl", strerror(errno));
+ return -1;
+ }
+
+ /* Optimize TCP settings */
+
+ option = 1;
+ setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option));
+#ifdef HAVE_LINUX
+ setsockopt(nfd, SOL_TCP, TCP_NODELAY, &option, sizeof(option));
+
+ option = IPTOS_LOWDELAY;
+ setsockopt(nfd, SOL_IP, IP_TOS, &option, sizeof(option));
+
+ if(get_config_string(lookup_config(config_tree, "BindToInterface"), &interface))
+ if(setsockopt(nfd, SOL_SOCKET, SO_BINDTODEVICE, interface, strlen(interface)))
+ {
+ close(nfd);
+ syslog(LOG_ERR, _("Can't bind to interface %s: %s"), interface, strerror(errno));
+ return -1;
+ }
+#endif
+
+ if(bind(nfd, &sa->sa, sizeof(*sa)))
+ {
+ close(nfd);
+ addrstr = sockaddr2hostname(sa);
+ syslog(LOG_ERR, _("Can't bind to %s/tcp: %s"), addrstr, strerror(errno));
+ free(addrstr);
+ return -1;
+ }
+
+ if(listen(nfd, 3))
+ {
+ close(nfd);
+ syslog(LOG_ERR, _("System call `%s' failed: %s"), "listen", strerror(errno));
+ return -1;
+ }
+cp
+ return nfd;
+}
+
+int setup_vpn_in_socket(sockaddr_t *sa)
+{
+ int nfd, flags;
+ char *addrstr;
+ int option;
+#ifdef HAVE_LINUX
+ char *interface;
+#endif
+cp
+ if((nfd = socket(sa->sa.sa_family, SOCK_DGRAM, IPPROTO_UDP)) < 0)
+ {
+ syslog(LOG_ERR, _("Creating UDP socket failed: %s"), strerror(errno));
+ return -1;
+ }
+
+ flags = fcntl(nfd, F_GETFL);
+ if(fcntl(nfd, F_SETFL, flags | O_NONBLOCK) < 0)
+ {
+ close(nfd);
+ syslog(LOG_ERR, _("System call `%s' failed: %s"), "fcntl", strerror(errno));
+ return -1;
+ }
+
+ option = 1;
+ setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option));
+#ifdef HAVE_LINUX
+ if(get_config_string(lookup_config(config_tree, "BindToInterface"), &interface))
+ if(setsockopt(nfd, SOL_SOCKET, SO_BINDTODEVICE, interface, strlen(interface)))
+ {
+ close(nfd);
+ syslog(LOG_ERR, _("Can't bind to interface %s: %s"), interface, strerror(errno));
+ return -1;
+ }
+#endif
+
+ if(bind(nfd, &sa->sa, sizeof(*sa)))
+ {
+ close(nfd);
+ addrstr = sockaddr2hostname(sa);
+ syslog(LOG_ERR, _("Can't bind to %s/udp: %s"), addrstr, strerror(errno));
+ free(addrstr);
+ return -1;
+ }
+cp
+ return nfd;
+}
+
+void retry_outgoing(outgoing_t *outgoing)
+{
+ event_t *event;
+cp
+ outgoing->timeout += 5;
+ if(outgoing->timeout > maxtimeout)
+ outgoing->timeout = maxtimeout;
+
+ event = new_event();
+ event->handler = (event_handler_t)setup_outgoing_connection;
+ event->time = time(NULL) + outgoing->timeout;
+ event->data = outgoing;
+ event_add(event);
+
+ if(debug_lvl >= DEBUG_CONNECTIONS)
+ syslog(LOG_NOTICE, _("Trying to re-establish outgoing connection in %d seconds"), outgoing->timeout);
+cp
+}
+
+int setup_outgoing_socket(connection_t *c)
+{
+ int option;
+cp
+ if(debug_lvl >= DEBUG_CONNECTIONS)
+ syslog(LOG_INFO, _("Trying to connect to %s (%s)"), c->name, c->hostname);
+
+ c->socket = socket(c->address.sa.sa_family, SOCK_STREAM, IPPROTO_TCP);
+
+ if(c->socket == -1)
+ {
+ syslog(LOG_ERR, _("Creating socket for %s failed: %s"), c->hostname, strerror(errno));
+ return -1;
+ }
+
+ /* Optimize TCP settings */
+
+#ifdef HAVE_LINUX
+ option = 1;
+ setsockopt(c->socket, SOL_TCP, TCP_NODELAY, &option, sizeof(option));
+
+ option = IPTOS_LOWDELAY;
+ setsockopt(c->socket, SOL_IP, IP_TOS, &option, sizeof(option));
+#endif
+
+ /* Connect */
+
+ if(connect(c->socket, &c->address.sa, sizeof(c->address)) == -1)
+ {
+ close(c->socket);
+ syslog(LOG_ERR, _("%s: %s"), c->hostname, strerror(errno));
+ return -1;
+ }
+
+ if(debug_lvl >= DEBUG_CONNECTIONS)
+ syslog(LOG_INFO, _("Connected to %s (%s)"), c->name, c->hostname);
+cp
+ return 0;
+}
+
+
+void finish_connecting(connection_t *c)
+{
+cp
+ if(debug_lvl >= DEBUG_CONNECTIONS)
+ syslog(LOG_INFO, _("Connected to %s (%s)"), c->name, c->hostname);
+
+ c->last_ping_time = time(NULL);
+
+ send_id(c);
+cp
+}
+
+void do_outgoing_connection(connection_t *c)
+{
+ char *address, *port;
+ int option, result, flags;
+cp
+begin:
+ if(!c->outgoing->ai)
+ {
+ if(!c->outgoing->cfg)
+ {
+ if(debug_lvl >= DEBUG_CONNECTIONS)
+ syslog(LOG_ERR, _("Could not set up a meta connection to %s"), c->name);
+ c->status.remove = 1;
+ do_prune = 1;
+ retry_outgoing(c->outgoing);
+ return;
+ }
+
+ get_config_string(c->outgoing->cfg, &address);
+
+ if(!get_config_string(lookup_config(c->config_tree, "Port"), &port))
+ asprintf(&port, "655");
+
+ c->outgoing->ai = str2addrinfo(address, port, SOCK_STREAM);
+ free(address);
+ free(port);
+
+ c->outgoing->aip = c->outgoing->ai;
+ c->outgoing->cfg = lookup_config_next(c->config_tree, c->outgoing->cfg);
+ }
+
+ if(!c->outgoing->aip)
+ {
+ freeaddrinfo(c->outgoing->ai);
+ c->outgoing->ai = NULL;
+ goto begin;
+ }
+
+ memcpy(&c->address, c->outgoing->aip->ai_addr, c->outgoing->aip->ai_addrlen);
+ c->outgoing->aip = c->outgoing->aip->ai_next;
+
+ if(c->hostname)
+ free(c->hostname);
+
+ c->hostname = sockaddr2hostname(&c->address);
+
+ if(debug_lvl >= DEBUG_CONNECTIONS)
+ syslog(LOG_INFO, _("Trying to connect to %s (%s)"), c->name, c->hostname);
+
+ c->socket = socket(c->address.sa.sa_family, SOCK_STREAM, IPPROTO_TCP);
+
+ if(c->socket == -1)
+ {
+ if(debug_lvl >= DEBUG_CONNECTIONS)
+ syslog(LOG_ERR, _("Creating socket for %s failed: %s"), c->hostname, strerror(errno));
+
+ goto begin;
+ }
+
+ /* Optimize TCP settings */
+
+#ifdef HAVE_LINUX
+ option = 1;
+ setsockopt(c->socket, SOL_TCP, TCP_NODELAY, &option, sizeof(option));
+
+ option = IPTOS_LOWDELAY;
+ setsockopt(c->socket, SOL_IP, IP_TOS, &option, sizeof(option));
+#endif
+
+ /* Non-blocking */
+
+ flags = fcntl(c->socket, F_GETFL);
+
+ if(fcntl(c->socket, F_SETFL, flags | O_NONBLOCK) < 0)
+ {
+ syslog(LOG_ERR, _("fcntl for %s: %s"), c->hostname, strerror(errno));
+ }
+
+ /* Connect */
+
+ result = connect(c->socket, &c->address.sa, sizeof(c->address));
+
+ if(result == -1)
+ {
+ if(errno == EINPROGRESS)
+ {
+ c->status.connecting = 1;
+ return;
+ }
+
+ close(c->socket);
+
+ if(debug_lvl >= DEBUG_CONNECTIONS)
+ syslog(LOG_ERR, _("%s: %s"), c->hostname, strerror(errno));
+
+ goto begin;
+ }
+
+ finish_connecting(c);
+ return;
+cp
+}
+
+void setup_outgoing_connection(outgoing_t *outgoing)
+{
+ connection_t *c;
+ node_t *n;
+cp
+ n = lookup_node(outgoing->name);
+
+ if(n)
+ if(n->connection)
+ {
+ if(debug_lvl >= DEBUG_CONNECTIONS)
+ syslog(LOG_INFO, _("Already connected to %s"), outgoing->name);
+ n->connection->outgoing = outgoing;
+ return;
+ }
+
+ c = new_connection();
+ c->name = xstrdup(outgoing->name);
+
+ init_configuration(&c->config_tree);
+ read_connection_config(c);
+
+ outgoing->cfg = lookup_config(c->config_tree, "Address");
+
+ if(!outgoing->cfg)
+ {
+ syslog(LOG_ERR, _("No address specified for %s"), c->name);
+ free_connection(c);
+ free(outgoing->name);
+ free(outgoing);
+ return;
+ }
+
+ c->outgoing = outgoing;
+ c->last_ping_time = time(NULL);
+
+ connection_add(c);
+
+ do_outgoing_connection(c);
+}
+
+/*
+ accept a new tcp connect and create a
+ new connection
+*/
+int handle_new_meta_connection()
+{
+ connection_t *c;
+ sockaddr_t sa;
+ int fd, len = sizeof(sa);
+cp
+ if((fd = accept(tcp_socket, &sa.sa, &len)) < 0)
+ {
+ syslog(LOG_ERR, _("Accepting a new connection failed: %s"), strerror(errno));
+ return -1;
+ }
+
+ c = new_connection();
+
+ c->address = sa;
+ c->hostname = sockaddr2hostname(&sa);
+ c->socket = fd;
+ c->last_ping_time = time(NULL);
+
+ if(debug_lvl >= DEBUG_CONNECTIONS)
+ syslog(LOG_NOTICE, _("Connection from %s"), c->hostname);
+
+ connection_add(c);
+
+ c->allow_request = ID;
+ send_id(c);
+cp
+ return 0;
+}
+
+void try_outgoing_connections(void)
+{
+ static config_t *cfg = NULL;
+ char *name;
+ outgoing_t *outgoing;
+cp
+ for(cfg = lookup_config(config_tree, "ConnectTo"); cfg; cfg = lookup_config_next(config_tree, cfg))
+ {
+ get_config_string(cfg, &name);
+
+ if(check_id(name))
+ {
+ syslog(LOG_ERR, _("Invalid name for outgoing connection in %s line %d"), cfg->file, cfg->line);
+ free(name);
+ continue;
+ }
+
+ outgoing = xmalloc_and_zero(sizeof(*outgoing));
+ outgoing->name = name;
+ setup_outgoing_connection(outgoing);
+ }
+}
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: device.c,v 1.1.2.1 2002/02/12 14:40:12 guus Exp $
+ $Id: device.c,v 1.1.2.2 2002/02/18 16:25:19 guus Exp $
*/
#include "config.h"
#include <stdio.h>
+#include <errno.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <sys/stat.h>
cp
if((device_fd = open(device, O_RDWR | O_NONBLOCK)) < 0)
{
- syslog(LOG_ERR, _("Could not open %s: %m"), device);
+ syslog(LOG_ERR, _("Could not open %s: %s"), device, strerror(errno));
return -1;
}
cp
if((lenin = readv(device_fd, vector, 2)) <= 0)
{
- syslog(LOG_ERR, _("Error while reading from %s %s: %m"), device_info, device);
+ syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info, device, strerror(errno));
return -1;
}
if(writev(device_fd, vector, 2) < 0)
{
- syslog(LOG_ERR, _("Can't write to %s %s: %m"), device_info, device);
+ syslog(LOG_ERR, _("Can't write to %s %s: %s"), device_info, device, strerror(errno));
return -1;
}
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: netutl.c,v 1.12.4.23 2002/02/11 10:16:18 guus Exp $
+ $Id: netutl.c,v 1.12.4.24 2002/02/18 16:25:16 guus Exp $
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <signal.h>
#include <sys/socket.h>
#include <syslog.h>
#include <arpa/inet.h>
#include "system.h"
-char *hostlookup(unsigned long addr)
+int hostnames = 0;
+
+/*
+ Turn a string into a struct addrinfo.
+ Return NULL on failure.
+*/
+struct addrinfo *str2addrinfo(char *address, char *service, int socktype)
{
- char *name;
- struct hostent *host = NULL;
- struct in_addr in;
- int lookup_hostname = 0;
+ struct addrinfo hint, *ai;
+ int err;
cp
- in.s_addr = addr;
-
- get_config_bool(lookup_config(config_tree, "Hostnames"), &lookup_hostname);
+ memset(&hint, 0, sizeof(hint));
- if(lookup_hostname)
- host = gethostbyaddr((char *)&in, sizeof(in), AF_INET);
+ hint.ai_family = addressfamily;
+ hint.ai_socktype = socktype;
- if(!lookup_hostname || !host)
+ if((err = getaddrinfo(address, service, &hint, &ai)))
{
- asprintf(&name, "%s", inet_ntoa(in));
+ if(debug_lvl >= DEBUG_ERROR)
+ syslog(LOG_WARNING, _("Error looking up %s port %s: %s\n"), address, service, gai_strerror(err));
+ cp_trace();
+ return NULL;
}
- else
+
+cp
+ return ai;
+}
+
+sockaddr_t str2sockaddr(char *address, char *port)
+{
+ struct addrinfo hint, *ai;
+ sockaddr_t result;
+ int err;
+cp
+ memset(&hint, 0, sizeof(hint));
+
+ hint.ai_family = AF_UNSPEC;
+ hint.ai_flags = AI_NUMERICHOST;
+ hint.ai_socktype = SOCK_STREAM;
+
+ if((err = getaddrinfo(address, port, &hint, &ai) || !ai))
{
- asprintf(&name, "%s", host->h_name);
+ syslog(LOG_ERR, _("Error looking up %s port %s: %s\n"), address, port, gai_strerror(err));
+ cp_trace();
+ raise(SIGFPE);
+ exit(0);
}
+
+ result = *(sockaddr_t *)ai->ai_addr;
+ freeaddrinfo(ai);
cp
- return name;
+ return result;
}
-/*
- Turn a string into an IP address
- return NULL on failure
- Should support IPv6 and other stuff in the future.
-*/
-ipv4_t str2address(char *str)
+void sockaddr2str(sockaddr_t *sa, char **addrstr, char **portstr)
{
- ipv4_t address;
- struct hostent *h;
+ char address[NI_MAXHOST];
+ char port[NI_MAXSERV];
+ int err;
cp
- if(!(h = gethostbyname(str)))
+ if((err = getnameinfo((struct sockaddr *)sa, sizeof(sockaddr_t), address, sizeof(address), port, sizeof(port), NI_NUMERICHOST|NI_NUMERICSERV)))
{
- if(debug_lvl >= DEBUG_ERROR)
- syslog(LOG_WARNING, _("Error looking up `%s': %s\n"), str, strerror(errno));
-
- return 0;
+ syslog(LOG_ERR, _("Error while translating addresses: %s"), gai_strerror(err));
+ cp_trace();
+ raise(SIGFPE);
+ exit(0);
}
- address = ntohl(*((ipv4_t*)(h->h_addr_list[0])));
+ *addrstr = xstrdup(address);
+ *portstr = xstrdup(port);
cp
- return address;
}
-char *address2str(ipv4_t address)
+char *sockaddr2hostname(sockaddr_t *sa)
{
char *str;
+ char address[NI_MAXHOST] = "unknown";
+ char port[NI_MAXSERV] = "unknown";
+ int err;
cp
- asprintf(&str, "%hu.%hu.%hu.%hu",
- (unsigned short int)((address >> 24) & 255),
- (unsigned short int)((address >> 16) & 255),
- (unsigned short int)((address >> 8) & 255),
- (unsigned short int)(address & 255));
+ if((err = getnameinfo((struct sockaddr *)sa, sizeof(sockaddr_t), address, sizeof(address), port, sizeof(port), hostnames?0:(NI_NUMERICHOST|NI_NUMERICSERV))))
+ {
+ syslog(LOG_ERR, _("Error while looking up hostname: %s"), gai_strerror(err));
+ }
+
+ asprintf(&str, _("%s port %s"), address, port);
cp
return str;
}
+
+int sockaddrcmp(sockaddr_t *a, sockaddr_t *b)
+{
+ int result;
+cp
+ result = a->sa.sa_family - b->sa.sa_family;
+
+ if(result)
+ return result;
+
+ switch(a->sa.sa_family)
+ {
+ case AF_UNSPEC:
+ return 0;
+ case AF_INET:
+ return memcmp(&a->in, &b->in, sizeof(a->in));
+ case AF_INET6:
+ return memcmp(&a->in6, &b->in6, sizeof(a->in6));
+ default:
+ syslog(LOG_ERR, _("sockaddrcmp() was called with unknown address family %d, exitting!"), a->sa.sa_family);
+ cp_trace();
+ raise(SIGFPE);
+ exit(0);
+ }
+cp
+}
+
+/* Subnet mask handling */
+
+int maskcmp(char *a, char *b, int masklen, int len)
+{
+ int i, m, result;
+cp
+ for(m = masklen, i = 0; m > 8; m -= 8, i++)
+ if((result = a[i] - b[i]))
+ return result;
+
+ if(m)
+ return (a[i] & (0x100 - (m << 1))) - (b[i] & (0x100 - (m << 1)));
+
+ return 0;
+}
+
+void mask(char *a, int masklen, int len)
+{
+ int i;
+cp
+ i = masklen / 8;
+ masklen %= 8;
+
+ if(masklen)
+ a[i++] &= (0x100 - (masklen << 1));
+
+ for(; i < len; i++)
+ a[i] = 0;
+}
+
+void maskcpy(char *a, char *b, int masklen, int len)
+{
+ int i, m;
+cp
+ for(m = masklen, i = 0; m > 8; m -= 8, i++)
+ a[i] = b[i];
+
+ if(m)
+ {
+ a[i] = b[i] & (0x100 - (m << 1));
+ i++;
+ }
+
+ for(; i < len; i++)
+ a[i] = 0;
+}
+
+int maskcheck(char *a, int masklen, int len)
+{
+ int i;
+cp
+ i = masklen / 8;
+ masklen %= 8;
+
+ if(masklen)
+ if(a[i++] & ~(0x100 - (masklen << 1)))
+ return -1;
+
+ for(; i < len; i++)
+ if(a[i] != 0)
+ return -1;
+
+ return 0;
+}
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: netutl.h,v 1.2.4.9 2002/02/11 10:16:18 guus Exp $
+ $Id: netutl.h,v 1.2.4.10 2002/02/18 16:25:16 guus Exp $
*/
#ifndef __TINC_NETUTL_H__
#define __TINC_NETUTL_H__
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+
#include "net.h"
+extern int hostnames;
+
extern char *hostlookup(unsigned long);
-extern ipv4_t str2address(char*);
-extern char *address2str(ipv4_t);
+extern struct addrinfo *str2addrinfo(char *, char *, int);
+extern sockaddr_t str2sockaddr(char *, char *);
+extern void sockaddr2str(sockaddr_t *, char **, char **);
+extern char *sockaddr2hostname(sockaddr_t *);
+extern int sockaddrcmp(sockaddr_t *, sockaddr_t *);
+extern int maskcmp(char *, char *, int, int);
+extern void maskcpy(char *, char *, int, int);
+extern void mask(char *, int, int);
+extern int maskcheck(char *, int, int);
#endif /* __TINC_NETUTL_H__ */
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: node.c,v 1.1.2.9 2002/02/11 15:59:18 guus Exp $
+ $Id: node.c,v 1.1.2.10 2002/02/18 16:25:16 guus Exp $
*/
#include "config.h"
#include <avl_tree.h>
#include "node.h"
+#include "netutl.h"
#include "net.h"
#include <utils.h>
#include <xalloc.h>
int node_udp_compare(node_t *a, node_t *b)
{
- if(a->address < b->address)
- return -1;
- if (a->address > b->address)
- return 1;
- if (a->port < b->port)
- return -1;
- if (a->port > b->port)
- return 1;
+ int result;
+cp
+ result = sockaddrcmp(&a->address, &b->address);
+
+ if(result)
+ return result;
+
return (a->name && b->name)?strcmp(a->name, b->name):0;
}
return avl_search(node_tree, &n);
}
-node_t *lookup_node_udp(ipv4_t address, port_t port)
+node_t *lookup_node_udp(sockaddr_t *sa)
{
node_t n;
cp
+ n.address = *sa;
n.name = NULL;
- n.address = address;
- n.port = port;
+
return avl_search(node_udp_tree, &n);
}
for(node = node_tree->head; node; node = node->next)
{
n = (node_t *)node->data;
- syslog(LOG_DEBUG, _(" %s at %s port %hd cipher %d digest %d maclength %d compression %d options %ld status %04x nexthop %s via %s"),
- n->name, n->hostname, n->port, n->cipher?n->cipher->nid:0, n->digest?n->digest->type:0, n->maclength, n->compression, n->options,
+ syslog(LOG_DEBUG, _(" %s at %s cipher %d digest %d maclength %d compression %d options %ld status %04x nexthop %s via %s"),
+ n->name, n->hostname, n->cipher?n->cipher->nid:0, n->digest?n->digest->type:0, n->maclength, n->compression, n->options,
n->status, n->nexthop?n->nexthop->name:"-", n->via?n->via->name:"-");
}
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: node.h,v 1.1.2.11 2002/02/11 15:59:18 guus Exp $
+ $Id: node.h,v 1.1.2.12 2002/02/18 16:25:16 guus Exp $
*/
#ifndef __TINC_NODE_H__
char *name; /* name of this node */
long int options; /* options turned on for this node */
- ipv4_t address; /* his real (internet) ip to send UDP packets to */
- port_t port; /* port number of UDP connection */
+ sockaddr_t address; /* his real (internet) ip to send UDP packets to */
char *hostname; /* the hostname of its real ip */
struct node_status_t status;
extern void init_nodes(void);
extern void exit_nodes(void);
extern node_t *new_node(void);
-extern void free_node(node_t *n);
-extern void node_add(node_t *n);
-extern void node_del(node_t *n);
+extern void free_node(node_t *);
+extern void node_add(node_t *);
+extern void node_del(node_t *);
extern node_t *lookup_node(char *);
-extern node_t *lookup_node_udp(ipv4_t, port_t);
+extern node_t *lookup_node_udp(sockaddr_t *);
extern void dump_nodes(void);
#endif /* __TINC_NODE_H__ */
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: device.c,v 1.1.2.4 2002/02/11 12:33:01 guus Exp $
+ $Id: device.c,v 1.1.2.5 2002/02/18 16:25:19 guus Exp $
*/
#include "config.h"
#include <stdio.h>
+#include <errno.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <sys/stat.h>
cp
if((device_fd = open(device, O_RDWR | O_NONBLOCK)) < 0)
{
- syslog(LOG_ERR, _("Could not open %s: %m"), device);
+ syslog(LOG_ERR, _("Could not open %s: %s"), device, strerror(errno));
return -1;
}
cp
if((lenin = readv(device_fd, vector, 2)) <= 0)
{
- syslog(LOG_ERR, _("Error while reading from %s %s: %m"), device_info, device);
+ syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info, device, strerror(errno));
return -1;
}
if(writev(device_fd, vector, 2) < 0)
{
- syslog(LOG_ERR, _("Can't write to %s %s: %m"), device_info, device);
+ syslog(LOG_ERR, _("Can't write to %s %s: %s"), device_info, device, strerror(errno));
return -1;
}
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: process.c,v 1.1.2.34 2002/02/12 14:29:00 guus Exp $
+ $Id: process.c,v 1.1.2.35 2002/02/18 16:25:16 guus Exp $
*/
#include "config.h"
cp
if((pid = fork()) < 0)
{
- syslog(LOG_ERR, _("System call `%s' failed: %m"),
- "fork");
+ syslog(LOG_ERR, _("System call `%s' failed: %s"), "fork", strerror(errno));
return -1;
}
}
else
{
- syslog(LOG_ERR, _("System call `%s' failed: %m"), "waitpid");
+ syslog(LOG_ERR, _("System call `%s' failed: %s"), "waitpid", strerror(errno));
return -1;
}
}
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: protocol_auth.c,v 1.1.4.1 2002/02/11 10:05:58 guus Exp $
+ $Id: protocol_auth.c,v 1.1.4.2 2002/02/18 16:25:16 guus Exp $
*/
#include "config.h"
to create node_t and edge_t structures. */
int x;
- char *addrstr;
+ char *address, *port;
struct timeval now;
cp
/* Estimate weight */
gettimeofday(&now, NULL);
c->estimated_weight = (now.tv_sec - c->start.tv_sec) * 1000 + (now.tv_usec - c->start.tv_usec) / 1000;
- addrstr = address2str(c->address);
- x = send_request(c, "%d %hd %s %d %d", ACK, myself->port, addrstr, c->estimated_weight, c->options);
- free(addrstr);
+ sockaddr2str(&c->address, &address, &port);
+ x = send_request(c, "%d %s %s %s %d %d", ACK, myport, address, port, c->estimated_weight, c->options);
+ free(address);
+ free(port);
cp
return x;
}
int ack_h(connection_t *c)
{
- port_t hisport;
- char addrstr[MAX_STRING_SIZE];
+ char address[MAX_STRING_SIZE];
+ char port[MAX_STRING_SIZE];
+ char hisport[MAX_STRING_SIZE];
+ char *hisaddress, *dummy;
int weight;
int options;
node_t *n;
connection_t *other;
avl_node_t *node;
cp
- if(sscanf(c->buffer, "%*d %hd "MAX_STRING" %d %d", &hisport, addrstr, &weight, &options) != 4)
+ if(sscanf(c->buffer, "%*d "MAX_STRING" "MAX_STRING" "MAX_STRING" %d %d", hisport, address, port, &weight, &options) != 5)
{
syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "ACK", c->name, c->hostname);
return -1;
{
n = new_node();
n->name = xstrdup(c->name);
- n->address = c->address;
- n->hostname = xstrdup(c->hostname);
- n->port = hisport;
-
- /* FIXME: Also check if no other tinc daemon uses the same IP and port for UDP traffic */
-
node_add(n);
}
else
/* Create an edge_t for this connection */
c->edge = new_edge();
-
+cp
c->edge->from.node = myself;
- c->edge->from.address = str2address(addrstr);
- c->edge->from.port = myself->port;
+ c->edge->from.tcpaddress = str2sockaddr(address, port);
+ c->edge->from.udpaddress = str2sockaddr(address, myport);
c->edge->to.node = n;
- c->edge->to.address = c->address;
- c->edge->to.port = hisport;
+ c->edge->to.tcpaddress = c->address;
+ sockaddr2str(&c->address, &hisaddress, &dummy);
+ c->edge->to.udpaddress = str2sockaddr(hisaddress, hisport);
+ free(hisaddress);
+ free(dummy);
c->edge->weight = (weight + c->estimated_weight) / 2;
c->edge->connection = c;
c->edge->options = c->options;
-
+cp
edge_add(c->edge);
/* Activate this connection */
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: protocol_edge.c,v 1.1.4.1 2002/02/11 10:05:58 guus Exp $
+ $Id: protocol_edge.c,v 1.1.4.2 2002/02/18 16:25:18 guus Exp $
*/
#include "config.h"
int send_add_edge(connection_t *c, edge_t *e)
{
int x;
- char *from_addrstr, *to_addrstr;
+ char *from_tcpaddress, *from_tcpport, *from_udpaddress, *from_udpport;
+ char *to_tcpaddress, *to_tcpport, *to_udpaddress, *to_udpport;
cp
- from_addrstr = address2str(e->from.address);
- to_addrstr = address2str(e->to.address);
- x = send_request(c, "%d %s %s %hd %s %s %hd %lx %d", ADD_EDGE,
- e->from.node->name, from_addrstr, e->from.port,
- e->to.node->name, to_addrstr, e->to.port,
+ sockaddr2str(&e->from.tcpaddress, &from_tcpaddress, &from_tcpport);
+ sockaddr2str(&e->from.udpaddress, &from_udpaddress, &from_udpport);
+ sockaddr2str(&e->to.tcpaddress, &to_tcpaddress, &to_tcpport);
+ sockaddr2str(&e->to.udpaddress, &to_udpaddress, &to_udpport);
+ x = send_request(c, "%d %s %s %s %s %s %s %s %s %lx %d", ADD_EDGE,
+ e->from.node->name, from_tcpaddress, from_tcpport, from_udpport,
+ e->to.node->name, to_tcpaddress, to_tcpport, to_udpport,
e->options, e->weight);
- free(from_addrstr);
- free(to_addrstr);
+ free(from_tcpaddress);
+ free(from_tcpport);
+ free(from_udpaddress);
+ free(from_udpport);
+ free(to_tcpaddress);
+ free(to_tcpport);
+ free(to_udpaddress);
+ free(to_udpport);
cp
return x;
}
node_t *from, *to;
char from_name[MAX_STRING_SIZE];
char to_name[MAX_STRING_SIZE];
- char from_addrstr[MAX_STRING_SIZE];
- char to_addrstr[MAX_STRING_SIZE];
- ipv4_t from_address, to_address;
- port_t from_port, to_port;
+ char from_address[MAX_STRING_SIZE];
+ char from_tcpport[MAX_STRING_SIZE];
+ char from_udpport[MAX_STRING_SIZE];
+ char to_address[MAX_STRING_SIZE];
+ char to_tcpport[MAX_STRING_SIZE];
+ char to_udpport[MAX_STRING_SIZE];
+ sockaddr_t from_tcpaddress, from_udpaddress;
+ sockaddr_t to_tcpaddress, to_udpaddress;
long int options;
int weight;
avl_node_t *node;
cp
- if(sscanf(c->buffer, "%*d "MAX_STRING" "MAX_STRING" %hd "MAX_STRING" "MAX_STRING" %hd %lx %d",
- from_name, from_addrstr, &from_port,
- to_name, to_addrstr, &to_port,
- &options, &weight) != 8)
+ if(sscanf(c->buffer, "%*d "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING" %lx %d",
+ from_name, from_address, from_tcpport, from_udpport,
+ to_name, to_address, to_tcpport, to_udpport,
+ &options, &weight) != 10)
{
syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "ADD_EDGE", c->name, c->hostname);
return -1;
/* Convert addresses */
- from_address = str2address(from_addrstr);
- to_address = str2address(to_addrstr);
+ from_tcpaddress = str2sockaddr(from_address, from_tcpport);
+ from_udpaddress = str2sockaddr(from_address, from_udpport);
+ to_tcpaddress = str2sockaddr(to_address, to_tcpport);
+ to_udpaddress = str2sockaddr(to_address, to_udpport);
/* Check if edge already exists */
if(e)
{
if(e->weight != weight || e->options != options
- || ((e->from.node == from) && (e->from.address != from_address || e->from.port != from_port || e->to.address != to_address || e->to.port != to_port))
- || ((e->from.node == to) && (e->from.address != to_address || e->from.port != to_port || e->to.address != from_address || e->to.port != from_port))
- )
+ || ((e->from.node == from) && (sockaddrcmp(&e->from.tcpaddress, &from_tcpaddress) || sockaddrcmp(&e->from.udpaddress, &from_udpaddress) || sockaddrcmp(&e->to.tcpaddress, &to_tcpaddress) || sockaddrcmp(&e->to.udpaddress, &to_udpaddress)))
+ || ((e->from.node == to) && (sockaddrcmp(&e->from.tcpaddress, &to_tcpaddress) || sockaddrcmp(&e->from.udpaddress, &to_udpaddress) || sockaddrcmp(&e->to.tcpaddress, &from_tcpaddress) || sockaddrcmp(&e->to.udpaddress, &from_udpaddress)))
+ )
{
if(from == myself || to == myself)
{
e = new_edge();
e->from.node = from;
- e->from.address = from_address;
- e->from.port = from_port;
+ e->from.tcpaddress = from_tcpaddress;
+ e->from.udpaddress = from_udpaddress;
e->to.node = to;
- e->to.address = to_address;
- e->to.port = to_port;
+ e->to.tcpaddress = to_tcpaddress;
+ e->to.udpaddress = to_udpaddress;
e->options = options;
e->weight = weight;
edge_add(e);
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: route.c,v 1.1.2.22 2002/02/10 21:57:54 guus Exp $
+ $Id: route.c,v 1.1.2.23 2002/02/18 16:25:19 guus Exp $
*/
#include "config.h"
node_t *route_ipv4(vpn_packet_t *packet)
{
- ipv4_t dest;
subnet_t *subnet;
cp
-#ifdef HAVE_SOLARIS
- /* The other form gives bus errors on a SparcStation 20. */
- dest = ((packet->data[30] * 0x100 + packet->data[31]) * 0x100 + packet->data[32]) * 0x100 + packet->data[33];
-#else
- dest = ntohl(*((unsigned long*)(&packet->data[30])));
-#endif
-cp
- subnet = lookup_subnet_ipv4(&dest);
+ subnet = lookup_subnet_ipv4((ipv4_t *)&packet->data[30]);
cp
if(!subnet)
{
if(debug_lvl >= DEBUG_TRAFFIC)
{
- syslog(LOG_WARNING, _("Cannot route packet: unknown destination address %d.%d.%d.%d"),
+ syslog(LOG_WARNING, _("Cannot route packet: unknown IPv4 destination address %d.%d.%d.%d"),
packet->data[30], packet->data[31], packet->data[32], packet->data[33]);
}
struct ether_arp *arp;
subnet_t *subnet;
unsigned char ipbuf[4];
- ipv4_t dest;
cp
/* First, snatch the source address from the ARP packet */
/* Check if the IP address exists on the VPN */
- dest = ntohl(*((unsigned long*)(arp->arp_tpa)));
- subnet = lookup_subnet_ipv4(&dest);
+ subnet = lookup_subnet_ipv4((ipv4_t *)arp->arp_tpa);
if(!subnet)
{
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: device.c,v 1.1.2.6 2002/02/11 14:20:46 guus Exp $
+ $Id: device.c,v 1.1.2.7 2002/02/18 16:25:19 guus Exp $
*/
#include "config.h"
#include <stdio.h>
+#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
cp
if((device_fd = open(device, O_RDWR | O_NONBLOCK)) < 0)
{
- syslog(LOG_ERR, _("Could not open %s: %m"), device);
+ syslog(LOG_ERR, _("Could not open %s: %s"), device, strerror(errno));
return -1;
}
cp
ppa = atoi(ptr);
if( (ip_fd = open("/dev/ip", O_RDWR, 0)) < 0){
- syslog(LOG_ERR, _("Could not open /dev/ip: %m"));
+ syslog(LOG_ERR, _("Could not open /dev/ip: %s"), strerror(errno));
return -1;
}
/* Assign a new PPA and get its unit number. */
if( (ppa = ioctl(device_fd, TUNNEWPPA, ppa)) < 0){
- syslog(LOG_ERR, _("Can't assign new interface: %m"));
+ syslog(LOG_ERR, _("Can't assign new interface: %s"), strerror(errno));
return -1;
}
if( (if_fd = open(device, O_RDWR, 0)) < 0){
- syslog(LOG_ERR, _("Could not open %s twice: %m"), device);
+ syslog(LOG_ERR, _("Could not open %s twice: %s"), device, strerror(errno));
return -1;
}
if(ioctl(if_fd, I_PUSH, "ip") < 0){
- syslog(LOG_ERR, _("Can't push IP module: %m"));
+ syslog(LOG_ERR, _("Can't push IP module: %s"), strerror(errno));
return -1;
}
/* Assign ppa according to the unit number returned by tun device */
if(ioctl(if_fd, IF_UNITSEL, (char *)&ppa) < 0){
- syslog(LOG_ERR, _("Can't set PPA %d: %m"), ppa);
+ syslog(LOG_ERR, _("Can't set PPA %d: %s"), ppa, strerror(errno));
return -1;
}
if(ioctl(ip_fd, I_LINK, if_fd) < 0){
- syslog(LOG_ERR, _("Can't link TUN device to IP: %m"));
+ syslog(LOG_ERR, _("Can't link TUN device to IP: %s"), strerror(errno));
return -1;
}
cp
if((lenin = read(device_fd, packet->data + 14, MTU - 14)) <= 0)
{
- syslog(LOG_ERR, _("Error while reading from %s %s: %m"), device_info, device);
+ syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info, device, strerror(errno));
return -1;
}
if(write(device_fd, packet->data + 14, packet->len - 14) < 0)
{
- syslog(LOG_ERR, _("Can't write to %s %s: %m"), device_info, packet->len);
+ syslog(LOG_ERR, _("Can't write to %s %s: %s"), device_info, packet->len, strerror(errno));
return -1;
}
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: subnet.c,v 1.1.2.29 2002/02/10 21:57:54 guus Exp $
+ $Id: subnet.c,v 1.1.2.30 2002/02/18 16:25:19 guus Exp $
*/
#include "config.h"
#include <netdb.h>
#include <netinet/in.h>
+#include <utils.h>
+#include <xalloc.h>
+#include <avl_tree.h>
+
#include "conf.h"
#include "net.h"
#include "node.h"
#include "subnet.h"
-#include "system.h"
+#include "netutl.h"
-#include <utils.h>
-#include <xalloc.h>
-#include <avl_tree.h>
+#include "system.h"
/* lists type of subnet */
int subnet_compare_ipv4(subnet_t *a, subnet_t *b)
{
+ int result;
cp
- /* We compare as if a subnet is a number that equals (address << 32 + netmask). */
-
- if(a->net.ipv4.address < b->net.ipv4.address)
- return -1;
- else if(a->net.ipv4.address > b->net.ipv4.address)
- return 1;
-
- if(a->net.ipv4.mask < b->net.ipv4.mask)
- return -1;
- else if(a->net.ipv4.mask > b->net.ipv4.mask)
- return 1;
+ result = memcmp(&a->net.ipv4.address, &b->net.ipv4.address, sizeof(ipv4_t));
+
+ if(result)
+ return result;
- return 0;
+ return a->net.ipv4.masklength - b->net.ipv4.masklength;
}
int subnet_compare_ipv6(subnet_t *a, subnet_t *b)
{
int result;
cp
- /* Same as ipv4 case, but with nasty 128 bit addresses */
-
- result = memcmp(a->net.ipv6.address.x, b->net.ipv6.address.x, sizeof(ipv6_t));
-
- if(result)
- return result;
-
- result = memcmp(a->net.ipv6.mask.x, b->net.ipv6.mask.x, sizeof(ipv6_t));
+ result = memcmp(&a->net.ipv6.address, &b->net.ipv6.address, sizeof(ipv6_t));
if(result)
return result;
- return 0;
+ return a->net.ipv6.masklength - b->net.ipv6.masklength;
}
int subnet_compare(subnet_t *a, subnet_t *b)
{
- int x;
+ int result;
cp
- x = a->type - b->type;
- if(x)
- return x;
+ result = a->type - b->type;
+
+ if(result)
+ return result;
switch(a->type)
{
{
int i, l;
subnet_t *subnet;
- unsigned short int x[6];
+ unsigned short int x[8];
cp
subnet = new_subnet();
cp
if(sscanf(subnetstr, "%hu.%hu.%hu.%hu/%d",
- &x[0],
- &x[1],
- &x[2],
- &x[3],
- &subnet->net.ipv4.masklength) == 5)
+ &x[0], &x[1], &x[2], &x[3],
+ &l) == 5)
{
subnet->type = SUBNET_IPV4;
- subnet->net.ipv4.address = (((((x[0] << 8) + x[1]) << 8) + x[2]) << 8) + x[3];
- subnet->net.ipv4.mask = ~((1 << (32 - subnet->net.ipv4.masklength)) - 1);
+ subnet->net.ipv4.masklength = l;
+ for(i = 0; i < 4; i++)
+ subnet->net.ipv4.address.x[i] = x[i];
return subnet;
}
if(sscanf(subnetstr, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx/%d",
- &subnet->net.ipv6.address.x[0],
- &subnet->net.ipv6.address.x[1],
- &subnet->net.ipv6.address.x[2],
- &subnet->net.ipv6.address.x[3],
- &subnet->net.ipv6.address.x[4],
- &subnet->net.ipv6.address.x[5],
- &subnet->net.ipv6.address.x[6],
- &subnet->net.ipv6.address.x[7],
- &subnet->net.ipv6.masklength) == 9)
+ &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7],
+ &l) == 9)
{
subnet->type = SUBNET_IPV6;
- for(l = subnet->net.ipv6.masklength, i = 0; i < 8; l -= 16, i++)
- {
- subnet->net.ipv6.address.x[i] = htons(subnet->net.ipv6.address.x[i]);
- if(l >= 16)
- subnet->net.ipv6.mask.x[i] = 65535;
- else if (l > 0)
- subnet->net.ipv6.mask.x[i] = htons(65536 - (1 << l));
- else
- subnet->net.ipv6.mask.x[i] = 0;
- }
+ subnet->net.ipv6.masklength = l;
+ for(i = 0; i < 8; i++)
+ subnet->net.ipv6.address.x[i] = htons(x[i]);
return subnet;
}
if(sscanf(subnetstr, "%hu.%hu.%hu.%hu",
- &x[0],
- &x[1],
- &x[2],
- &x[3]) == 4)
+ &x[0], &x[1], &x[2], &x[3]) == 4)
{
subnet->type = SUBNET_IPV4;
- subnet->net.ipv4.address = (((((x[0] << 8) + x[1]) << 8) + x[2]) << 8) + x[3];
- subnet->net.ipv4.mask = ~0;
subnet->net.ipv4.masklength = 32;
+ for(i = 0; i < 4; i++)
+ subnet->net.ipv4.address.x[i] = x[i];
return subnet;
}
if(sscanf(subnetstr, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx",
- &subnet->net.ipv6.address.x[0],
- &subnet->net.ipv6.address.x[1],
- &subnet->net.ipv6.address.x[2],
- &subnet->net.ipv6.address.x[3],
- &subnet->net.ipv6.address.x[4],
- &subnet->net.ipv6.address.x[5],
- &subnet->net.ipv6.address.x[6],
- &subnet->net.ipv6.address.x[7]) == 8)
+ &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7]) == 8)
{
subnet->type = SUBNET_IPV6;
subnet->net.ipv6.masklength = 128;
- for(l = subnet->net.ipv6.masklength, i = 0; i < 8; l -= 16, i++)
- {
- subnet->net.ipv6.address.x[i] = htons(subnet->net.ipv6.address.x[i]);
- if(l >= 16)
- subnet->net.ipv6.mask.x[i] = 65535;
- else if (l > 0)
- subnet->net.ipv6.mask.x[i] = htons(65536 - (1 << l));
- else
- subnet->net.ipv6.mask.x[i] = 0;
- }
+ for(i = 0; i < 8; i++)
+ subnet->net.ipv6.address.x[i] = htons(x[i]);
return subnet;
}
if(sscanf(subnetstr, "%hx:%hx:%hx:%hx:%hx:%hx",
- &x[0],
- &x[1],
- &x[2],
- &x[3],
- &x[4],
- &x[5]) == 6)
+ &x[0], &x[1], &x[2], &x[3], &x[4], &x[5]) == 6)
{
subnet->type = SUBNET_MAC;
- subnet->net.mac.address.x[0] = x[0];
- subnet->net.mac.address.x[1] = x[1];
- subnet->net.mac.address.x[2] = x[2];
- subnet->net.mac.address.x[3] = x[3];
- subnet->net.mac.address.x[4] = x[4];
- subnet->net.mac.address.x[5] = x[5];
+ for(i = 0; i < 6; i++)
+ subnet->net.mac.address.x[i] = x[i];
return subnet;
}
break;
case SUBNET_IPV4:
asprintf(&netstr, "%hu.%hu.%hu.%hu/%d",
- (unsigned short int)((subnet->net.ipv4.address >> 24) & 255),
- (unsigned short int)((subnet->net.ipv4.address >> 16) & 255),
- (unsigned short int)((subnet->net.ipv4.address >> 8) & 255),
- (unsigned short int)(subnet->net.ipv4.address & 255),
+ subnet->net.ipv4.address.x[0],
+ subnet->net.ipv4.address.x[1],
+ subnet->net.ipv4.address.x[2],
+ subnet->net.ipv4.address.x[3],
subnet->net.ipv4.masklength);
break;
case SUBNET_IPV6:
subnet->net.ipv6.masklength);
break;
default:
- asprintf(&netstr, _("unknown subnet type"));
+ syslog(LOG_ERR, _("net2str() was called with unknown subnet type %d, exitting!"), subnet->type);
+ cp_trace();
+ exit(0);
}
cp
return netstr;
subnet_t subnet, *p;
cp
subnet.type = SUBNET_IPV4;
- subnet.net.ipv4.address = *address;
- subnet.net.ipv4.mask = 0xFFFFFFFF;
+ memcpy(&subnet.net.ipv4.address, address, sizeof(ipv4_t));
+ subnet.net.ipv4.masklength = 32;
do
{
cp
if(p)
{
- if ((*address & p->net.ipv4.mask) == p->net.ipv4.address)
+ if(p->type != SUBNET_IPV4)
+ return NULL;
+
+ if (!maskcmp((char *)address, (char *)&p->net.ipv4.address, p->net.ipv4.masklength, sizeof(ipv4_t)))
break;
else
{
/* Otherwise, see if there is a bigger enclosing subnet */
- subnet.net.ipv4.mask = p->net.ipv4.mask << 1;
- subnet.net.ipv4.address = p->net.ipv4.address & subnet.net.ipv4.mask;
+ subnet.net.ipv4.masklength = p->net.ipv4.masklength - 1;
+ maskcpy((char *)&subnet.net.ipv4.address, (char *)&p->net.ipv4.address, subnet.net.ipv4.masklength, sizeof(ipv4_t));
}
}
} while (p);
subnet_t *lookup_subnet_ipv6(ipv6_t *address)
{
subnet_t subnet, *p;
- int i;
cp
subnet.type = SUBNET_IPV6;
- memcpy(subnet.net.ipv6.address.x, address, sizeof(ipv6_t));
- memset(subnet.net.ipv6.mask.x, 0xFF, 16);
+ memcpy(&subnet.net.ipv6.address, address, sizeof(ipv6_t));
+ subnet.net.ipv6.masklength = 128;
- p = (subnet_t *)avl_search_closest_greater(subnet_tree, &subnet);
+ do
+ {
+ /* Go find subnet */
- if(p)
- for(i=0; i<8; i++)
- if((address->x[i] & p->net.ipv6.address.x[i]) != p->net.ipv6.address.x[i])
- return NULL;
+ p = (subnet_t *)avl_search_closest_smaller(subnet_tree, &subnet);
+
+ /* Check if the found subnet REALLY matches */
+
+cp
+ if(p)
+ {
+ if(p->type != SUBNET_IPV6)
+ return NULL;
+
+ if (!maskcmp((char *)address, (char *)&p->net.ipv6.address, p->net.ipv6.masklength, sizeof(ipv6_t)))
+ break;
+ else
+ {
+ /* Otherwise, see if there is a bigger enclosing subnet */
+
+ subnet.net.ipv6.masklength = p->net.ipv6.masklength - 1;
+ maskcpy((char *)&subnet.net.ipv6.address, (char *)&p->net.ipv6.address, subnet.net.ipv6.masklength, sizeof(ipv6_t));
+ }
+ }
+ } while (p);
return p;
}
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: subnet.h,v 1.1.2.15 2002/02/10 21:57:54 guus Exp $
+ $Id: subnet.h,v 1.1.2.16 2002/02/18 16:25:19 guus Exp $
*/
#ifndef __TINC_SUBNET_H__
typedef struct subnet_ipv4_t
{
ipv4_t address;
- ipv4_t mask;
int masklength;
} subnet_ipv4_t;
typedef struct subnet_ipv6_t
{
ipv6_t address;
- ipv6_t mask;
int masklength;
} subnet_ipv6_t;