From c2b9c06062d36bde859b630b99a08c7b7428e721 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Mon, 18 Feb 2002 16:25:19 +0000 Subject: [PATCH] - Non-blocking connect()s. - 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. --- doc/tinc.conf.5 | 6 + doc/tinc.texi | 12 +- po/POTFILES.in | 6 +- po/nl.po | 688 +++++++++++---------- src/Makefile.am | 8 +- src/conf.c | 109 ++-- src/conf.h | 8 +- src/connection.c | 19 +- src/connection.h | 9 +- src/edge.c | 35 +- src/edge.h | 8 +- src/freebsd/device.c | 9 +- src/graph.c | 10 +- src/linux/device.c | 13 +- src/meta.c | 10 +- src/net.c | 1379 ++++-------------------------------------- src/net.h | 37 +- src/net_packet.c | 391 ++++++++++++ src/net_setup.c | 557 +++++++++++++++++ src/net_socket.c | 456 ++++++++++++++ src/netbsd/device.c | 9 +- src/netutl.c | 194 ++++-- src/netutl.h | 19 +- src/node.c | 28 +- src/node.h | 13 +- src/openbsd/device.c | 9 +- src/process.c | 7 +- src/protocol_auth.c | 40 +- src/protocol_edge.c | 67 +- src/route.c | 18 +- src/solaris/device.c | 21 +- src/subnet.c | 192 +++--- src/subnet.h | 4 +- 33 files changed, 2430 insertions(+), 1961 deletions(-) create mode 100644 src/net_packet.c create mode 100644 src/net_setup.c create mode 100644 src/net_socket.c diff --git a/doc/tinc.conf.5 b/doc/tinc.conf.5 index 642cc6b..9a1ca75 100644 --- a/doc/tinc.conf.5 +++ b/doc/tinc.conf.5 @@ -100,6 +100,12 @@ If you leave it out, remember to replace it with at least one space character. 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 diff --git a/doc/tinc.texi b/doc/tinc.texi index 6bf9c1d..d5ddbff 100644 --- a/doc/tinc.texi +++ b/doc/tinc.texi @@ -1,5 +1,5 @@ \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 @@ -18,7 +18,7 @@ Copyright @copyright{} 1998-2002 Ivo Timmermans , Guus Sliepen and Wessel Dankers . -$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 @@ -43,7 +43,7 @@ Copyright @copyright{} 1998-2002 Ivo Timmermans , Guus Sliepen and Wessel Dankers . -$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 @@ -736,6 +736,12 @@ required directives are given in @strong{bold}. @subsection Main configuration variables @table @asis +@cindex AddressFamily +@item AddressFamily = (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 = If you have more than one network interface in your computer, tinc will diff --git a/po/POTFILES.in b/po/POTFILES.in index 05a1201..4e52a3a 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -9,6 +9,9 @@ src/conf.c 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 @@ -25,5 +28,6 @@ src/edge.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 diff --git a/po/nl.po b/po/nl.po index 776e36d..15b0de2 100644 --- a/po/nl.po +++ b/po/nl.po @@ -5,7 +5,7 @@ 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 \n" "Language-Team: Dutch \n" @@ -24,22 +24,24 @@ msgstr "" 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 " @@ -48,71 +50,71 @@ msgstr "" "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" @@ -122,16 +124,16 @@ msgstr "" "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." @@ -142,13 +144,13 @@ msgstr "Verzenden van %d bytes metadata naar %s (%s)" #: 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 @@ -162,330 +164,355 @@ msgstr "Verbinding be #: 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 @@ -538,16 +565,16 @@ msgid "Bogus data received from %s (%s)" 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 @@ -603,7 +630,7 @@ msgstr "verkeerd antwoord op uitdaging" 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" @@ -613,33 +640,33 @@ 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" @@ -708,26 +735,27 @@ msgstr "Kreeg %s van %s (%s) voor %s welke niet voorkomt in de node boom" 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." @@ -855,7 +883,7 @@ msgstr "Onherstelbare fout" 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." @@ -906,56 +934,56 @@ msgstr "tincd %s (%s %s) start, debug niveau %d" 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 " @@ -964,21 +992,21 @@ msgstr "" "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" @@ -988,12 +1016,12 @@ 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:%" @@ -1002,16 +1030,16 @@ msgstr "" "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" @@ -1023,149 +1051,153 @@ msgstr "Nodes:" #: 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" diff --git a/src/Makefile.am b/src/Makefile.am index 7ea85a1..d769071 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,13 +1,13 @@ ## 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 diff --git a/src/conf.c b/src/conf.c index fc82372..3bf9b85 100644 --- a/src/conf.c +++ b/src/conf.c @@ -19,7 +19,7 @@ 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" @@ -56,14 +56,14 @@ char *netname = NULL; /* name of the vpn network */ 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 @@ -90,7 +90,7 @@ config_t *new_config(void) config_t *cfg; cp cfg = (config_t *)xmalloc_and_zero(sizeof(*cfg)); - + return cfg; } @@ -126,7 +126,7 @@ cp if(!found) return NULL; - + if(strcmp(found->variable, variable)) return NULL; @@ -139,7 +139,7 @@ config_t *lookup_config_next(avl_tree_t *config_tree, config_t *cfg) config_t *found; cp node = avl_search_node(config_tree, cfg); - + if(node) { if(node->next) @@ -149,10 +149,10 @@ cp return found; } } - + return NULL; } - + int get_config_bool(config_t *cfg, int *result) { cp @@ -184,7 +184,7 @@ 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; @@ -196,27 +196,26 @@ cp 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; } @@ -228,8 +227,11 @@ cp 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; @@ -250,20 +252,20 @@ cp 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; } @@ -271,7 +273,7 @@ cp 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 @@ -360,17 +362,17 @@ int read_config_file(avl_tree_t *config_tree, const char *fname) 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) @@ -395,7 +397,7 @@ cp if(!strcmp(variable, "-----BEGIN")) ignore = 1; - + if(!ignore) { if(((value = strtok(NULL, "\t\n\r =")) == NULL) || value[0] == '#') @@ -433,12 +435,11 @@ cp 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) @@ -466,10 +467,10 @@ int is_safe_path(const char *file) } p = strrchr(file, '/'); - + if(p == file) /* It's in the root */ p++; - + x = *p; *p = '\0'; @@ -477,8 +478,7 @@ int is_safe_path(const char *file) 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; } @@ -496,25 +496,24 @@ check1: 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; @@ -532,10 +531,10 @@ check2: 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; } @@ -547,7 +546,7 @@ check2: f); return 0; } - + return 1; } @@ -587,7 +586,7 @@ FILE *ask_and_safe_open(const char* filename, const char* what, const char* mode { /* The directory is a relative path or a filename. */ char *p; - + directory = get_current_dir_name(); asprintf(&p, "%s/%s", directory, fn); free(fn); @@ -596,7 +595,7 @@ FILE *ask_and_safe_open(const char* filename, const char* what, const char* mode } umask(0077); /* Disallow everything for group and other */ - + /* Open it first to keep the inode busy */ if((r = fopen(fn, mode)) == NULL) { @@ -605,7 +604,7 @@ FILE *ask_and_safe_open(const char* filename, const char* what, const char* mode 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. */ diff --git a/src/conf.h b/src/conf.h index a04d668..bf399dd 100644 --- a/src/conf.h +++ b/src/conf.h @@ -17,12 +17,16 @@ 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 +#include +#include + #include #include "net.h" #include "subnet.h" @@ -54,7 +58,7 @@ extern int get_config_bool(config_t *, int *); 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 **); diff --git a/src/connection.c b/src/connection.c index 815de4b..8620e4a 100644 --- a/src/connection.c +++ b/src/connection.c @@ -17,7 +17,7 @@ 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" @@ -44,7 +44,7 @@ avl_tree_t *connection_tree; /* Meta connections */ int connection_compare(connection_t *a, connection_t *b) { - return a->socket - b->socket; + return a - b; } void init_connections(void) @@ -106,16 +106,6 @@ cp 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; @@ -126,9 +116,8 @@ cp 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.")); diff --git a/src/connection.h b/src/connection.h index 1689aee..436f192 100644 --- a/src/connection.h +++ b/src/connection.h @@ -17,7 +17,7 @@ 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__ @@ -52,6 +52,7 @@ 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 */ @@ -64,8 +65,7 @@ typedef struct connection_status_t { 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 */ @@ -77,7 +77,7 @@ typedef struct connection_t { 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 */ @@ -109,7 +109,6 @@ extern connection_t *new_connection(void); 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 *); diff --git a/src/edge.c b/src/edge.c index 1851f51..b834879 100644 --- a/src/edge.c +++ b/src/edge.c @@ -17,7 +17,7 @@ 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" @@ -47,7 +47,7 @@ int edge_compare(edge_t *a, edge_t *b) int result; result = strcmp(a->from.node->name, b->from.node->name); - + if(result) return result; else @@ -69,7 +69,7 @@ int edge_name_compare(edge_t *a, edge_t *b) { 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 @@ -81,7 +81,7 @@ int edge_name_compare(edge_t *a, edge_t *b) name_b1 = b->to.node->name, name_b2 = b->from.node->name; result = strcmp(name_a1, name_b1); - + if(result) return result; else @@ -91,9 +91,9 @@ int edge_name_compare(edge_t *a, edge_t *b) int edge_weight_compare(edge_t *a, edge_t *b) { int result; - + result = a->weight - b->weight; - + if(result) return result; else @@ -189,23 +189,28 @@ void dump_edges(void) { 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 } diff --git a/src/edge.h b/src/edge.h index 9a60af6..e3fa078 100644 --- a/src/edge.h +++ b/src/edge.h @@ -17,7 +17,7 @@ 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__ @@ -25,14 +25,14 @@ #include +#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 { diff --git a/src/freebsd/device.c b/src/freebsd/device.c index e75076a..2f5f32e 100644 --- a/src/freebsd/device.c +++ b/src/freebsd/device.c @@ -17,12 +17,13 @@ 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 +#include #include #include #include @@ -66,7 +67,7 @@ cp 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 @@ -104,7 +105,7 @@ int read_packet(vpn_packet_t *packet) 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; } @@ -129,7 +130,7 @@ cp 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; } diff --git a/src/graph.c b/src/graph.c index 0847b28..abc918d 100644 --- a/src/graph.c +++ b/src/graph.c @@ -17,7 +17,7 @@ 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: @@ -186,17 +186,15 @@ void sssp_bfs(void) 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); diff --git a/src/linux/device.c b/src/linux/device.c index 88355ca..450fcd1 100644 --- a/src/linux/device.c +++ b/src/linux/device.c @@ -17,12 +17,13 @@ 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 +#include #include #include #include @@ -85,7 +86,7 @@ cp 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 @@ -154,7 +155,7 @@ 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; } @@ -164,7 +165,7 @@ cp { 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; } @@ -193,7 +194,7 @@ cp { 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; } } @@ -202,7 +203,7 @@ cp *(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; } } diff --git a/src/meta.c b/src/meta.c index e108ea1..f2326d1 100644 --- a/src/meta.c +++ b/src/meta.c @@ -17,7 +17,7 @@ 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" @@ -60,7 +60,7 @@ cp 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 @@ -91,7 +91,7 @@ int receive_meta(connection_t *c) 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; } @@ -125,8 +125,8 @@ cp 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; } diff --git a/src/net.c b/src/net.c index 3328863..bf58cf0 100644 --- a/src/net.c +++ b/src/net.c @@ -17,7 +17,7 @@ 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" @@ -46,1067 +46,32 @@ #include #include -#include -#include -#include -#ifndef HAVE_RAND_PSEUDO_BYTES -#define RAND_pseudo_bytes RAND_bytes -#endif - -#include - -#include -#include -#include -#include - -#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 +#include +#include +#include - 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 @@ -1130,53 +95,6 @@ cp 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) @@ -1203,36 +121,36 @@ cp 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 } @@ -1250,13 +168,13 @@ void terminate_connection(connection_t *c, int report) 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); @@ -1276,7 +194,7 @@ cp } /* Run MST and SSSP algorithms */ - + graph(); /* Check if this was our outgoing connection */ @@ -1323,10 +241,10 @@ cp 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 { @@ -1345,60 +263,6 @@ cp 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 @@ -1407,7 +271,16 @@ void check_network_activity(fd_set *f) { 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(); @@ -1416,14 +289,31 @@ cp 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)) @@ -1442,9 +332,9 @@ cp c = (connection_t *)node->data; if(c->status.remove) - connection_del(c); + connection_del(c); } - + if(!connection_tree->head) purge(); cp @@ -1461,7 +351,6 @@ void main_loop(void) time_t last_ping_check; int t; event_t *event; - vpn_packet_t packet; cp last_ping_check = time(NULL); @@ -1472,57 +361,39 @@ cp 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? */ @@ -1536,37 +407,47 @@ cp 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 diff --git a/src/net.h b/src/net.h index 93ac391..1100071 100644 --- a/src/net.h +++ b/src/net.h @@ -17,12 +17,15 @@ 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 +#include +#include #include #include "config.h" @@ -37,7 +40,10 @@ typedef struct mac_t 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; @@ -53,6 +59,14 @@ typedef unsigned short port_t; 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) */ @@ -73,16 +87,35 @@ typedef struct packet_queue_t { 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); diff --git a/src/net_packet.c b/src/net_packet.c new file mode 100644 index 0000000..5171a4f --- /dev/null +++ b/src/net_packet.c @@ -0,0 +1,391 @@ +/* + net_packet.c -- Handles in- and outgoing VPN packets + Copyright (C) 1998-2002 Ivo Timmermans , + 2000-2002 Guus Sliepen + + 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 +#include +#include +#include +#ifdef HAVE_LINUX + #include + #include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* SunOS really wants sys/socket.h BEFORE net/if.h, + and FreeBSD wants these lines below the rest. */ +#include +#include +#include + +#include +#include +#include +#include + +#ifndef HAVE_RAND_PSEUDO_BYTES +#define RAND_pseudo_bytes RAND_bytes +#endif + +#include + +#include +#include +#include +#include + +#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 +} + diff --git a/src/net_setup.c b/src/net_setup.c new file mode 100644 index 0000000..1c5ff15 --- /dev/null +++ b/src/net_setup.c @@ -0,0 +1,557 @@ +/* + net_setup.c -- Setup. + Copyright (C) 1998-2002 Ivo Timmermans , + 2000-2002 Guus Sliepen + + 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 +#include +#include +#include +#ifdef HAVE_LINUX + #include + #include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* SunOS really wants sys/socket.h BEFORE net/if.h, + and FreeBSD wants these lines below the rest. */ +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#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; +} diff --git a/src/net_socket.c b/src/net_socket.c new file mode 100644 index 0000000..93314fb --- /dev/null +++ b/src/net_socket.c @@ -0,0 +1,456 @@ +/* + net_socket.c -- Handle various kinds of sockets. + Copyright (C) 1998-2002 Ivo Timmermans , + 2000-2002 Guus Sliepen + + 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 +#include +#include +#include +#ifdef HAVE_LINUX + #include + #include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* SunOS really wants sys/socket.h BEFORE net/if.h, + and FreeBSD wants these lines below the rest. */ +#include +#include +#include + +#include +#include +#include +#include + +#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); + } +} diff --git a/src/netbsd/device.c b/src/netbsd/device.c index ed8cb4e..a8c01f5 100644 --- a/src/netbsd/device.c +++ b/src/netbsd/device.c @@ -17,12 +17,13 @@ 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 +#include #include #include #include @@ -70,7 +71,7 @@ int setup_device(void) 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 @@ -107,7 +108,7 @@ 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; } @@ -145,7 +146,7 @@ cp 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; } diff --git a/src/netutl.c b/src/netutl.c index 14ed5ce..2ad30fc 100644 --- a/src/netutl.c +++ b/src/netutl.c @@ -17,7 +17,7 @@ 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" @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -42,64 +43,183 @@ #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; +} diff --git a/src/netutl.h b/src/netutl.h index 3d1584f..6207fd1 100644 --- a/src/netutl.h +++ b/src/netutl.h @@ -17,16 +17,29 @@ 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 +#include +#include + #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__ */ diff --git a/src/node.c b/src/node.c index 2abd7fb..6e3b0f9 100644 --- a/src/node.c +++ b/src/node.c @@ -17,7 +17,7 @@ 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" @@ -27,6 +27,7 @@ #include #include "node.h" +#include "netutl.h" #include "net.h" #include #include @@ -45,14 +46,13 @@ int node_compare(node_t *a, node_t *b) 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; } @@ -143,13 +143,13 @@ cp 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); } @@ -163,8 +163,8 @@ cp 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:"-"); } diff --git a/src/node.h b/src/node.h index b662ccd..6493852 100644 --- a/src/node.h +++ b/src/node.h @@ -17,7 +17,7 @@ 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__ @@ -41,8 +41,7 @@ typedef struct node_t { 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; @@ -78,11 +77,11 @@ extern avl_tree_t *node_udp_tree; 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__ */ diff --git a/src/openbsd/device.c b/src/openbsd/device.c index a24d2d0..8468b19 100644 --- a/src/openbsd/device.c +++ b/src/openbsd/device.c @@ -17,12 +17,13 @@ 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 +#include #include #include #include @@ -70,7 +71,7 @@ int setup_device(void) 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 @@ -107,7 +108,7 @@ 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; } @@ -145,7 +146,7 @@ cp 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; } diff --git a/src/process.c b/src/process.c index 4455b65..5cc32c6 100644 --- a/src/process.c +++ b/src/process.c @@ -17,7 +17,7 @@ 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" @@ -255,8 +255,7 @@ int execute_script(const char *name) 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; } @@ -291,7 +290,7 @@ cp } else { - syslog(LOG_ERR, _("System call `%s' failed: %m"), "waitpid"); + syslog(LOG_ERR, _("System call `%s' failed: %s"), "waitpid", strerror(errno)); return -1; } } diff --git a/src/protocol_auth.c b/src/protocol_auth.c index 1fad4b7..8541d3d 100644 --- a/src/protocol_auth.c +++ b/src/protocol_auth.c @@ -17,7 +17,7 @@ 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" @@ -413,16 +413,17 @@ int send_ack(connection_t *c) 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; } @@ -462,15 +463,17 @@ void send_everything(connection_t *c) 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; @@ -484,12 +487,6 @@ cp { 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 @@ -512,17 +509,20 @@ cp /* 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 */ diff --git a/src/protocol_edge.c b/src/protocol_edge.c index 9c83199..0c5ca35 100644 --- a/src/protocol_edge.c +++ b/src/protocol_edge.c @@ -17,7 +17,7 @@ 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" @@ -48,16 +48,25 @@ 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; } @@ -69,18 +78,22 @@ int add_edge_h(connection_t *c) 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; @@ -122,8 +135,10 @@ cp /* 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 */ @@ -132,9 +147,9 @@ cp 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) { @@ -169,11 +184,11 @@ cp 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); diff --git a/src/route.c b/src/route.c index 0e16565..1ac3e12 100644 --- a/src/route.c +++ b/src/route.c @@ -17,7 +17,7 @@ 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" @@ -105,23 +105,15 @@ cp 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]); } @@ -163,7 +155,6 @@ void route_arp(vpn_packet_t *packet) struct ether_arp *arp; subnet_t *subnet; unsigned char ipbuf[4]; - ipv4_t dest; cp /* First, snatch the source address from the ARP packet */ @@ -193,8 +184,7 @@ cp /* 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) { diff --git a/src/solaris/device.c b/src/solaris/device.c index cf0bb53..758068d 100644 --- a/src/solaris/device.c +++ b/src/solaris/device.c @@ -17,13 +17,14 @@ 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 +#include #include #include #include @@ -71,7 +72,7 @@ cp 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 @@ -82,34 +83,34 @@ 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; } @@ -145,7 +146,7 @@ int read_packet(vpn_packet_t *packet) 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; } @@ -176,7 +177,7 @@ cp 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; } diff --git a/src/subnet.c b/src/subnet.c index 6745e2f..5fdc045 100644 --- a/src/subnet.c +++ b/src/subnet.c @@ -17,7 +17,7 @@ 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" @@ -30,15 +30,17 @@ #include #include +#include +#include +#include + #include "conf.h" #include "net.h" #include "node.h" #include "subnet.h" -#include "system.h" +#include "netutl.h" -#include -#include -#include +#include "system.h" /* lists type of subnet */ @@ -54,48 +56,36 @@ cp 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) { @@ -186,101 +176,58 @@ subnet_t *str2net(char *subnetstr) { 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; } @@ -305,10 +252,10 @@ cp 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: @@ -324,7 +271,9 @@ cp 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; @@ -355,8 +304,8 @@ subnet_t *lookup_subnet_ipv4(ipv4_t *address) 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 { @@ -368,14 +317,17 @@ cp 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); @@ -386,18 +338,36 @@ cp 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; } diff --git a/src/subnet.h b/src/subnet.h index 9657ad9..04e5c28 100644 --- a/src/subnet.h +++ b/src/subnet.h @@ -17,7 +17,7 @@ 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__ @@ -41,14 +41,12 @@ typedef struct subnet_mac_t 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; -- 2.25.1