- Non-blocking connect()s.
authorGuus Sliepen <guus@tinc-vpn.org>
Mon, 18 Feb 2002 16:25:19 +0000 (16:25 +0000)
committerGuus Sliepen <guus@tinc-vpn.org>
Mon, 18 Feb 2002 16:25:19 +0000 (16:25 +0000)
- 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.

33 files changed:
doc/tinc.conf.5
doc/tinc.texi
po/POTFILES.in
po/nl.po
src/Makefile.am
src/conf.c
src/conf.h
src/connection.c
src/connection.h
src/edge.c
src/edge.h
src/freebsd/device.c
src/graph.c
src/linux/device.c
src/meta.c
src/net.c
src/net.h
src/net_packet.c [new file with mode: 0644]
src/net_setup.c [new file with mode: 0644]
src/net_socket.c [new file with mode: 0644]
src/netbsd/device.c
src/netutl.c
src/netutl.h
src/node.c
src/node.h
src/openbsd/device.c
src/process.c
src/protocol_auth.c
src/protocol_edge.c
src/route.c
src/solaris/device.c
src/subnet.c
src/subnet.h

index 642cc6b35d356e6a940e72b14345728314bf404c..9a1ca75dcb00315eeaf781051d55d22da45beb34 100644 (file)
@@ -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
index 6bf9c1d15be477568ab6bcd7fda9090997e1924e..d5ddbff012f30c4194e0ac5db2ab5e44e1a302f5 100644 (file)
@@ -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
 <itimmermans@@bigfoot.com>, Guus Sliepen <guus@@sliepen.warande.net> and
 Wessel Dankers <wsl@@nl.linux.org>.
 
-$Id: tinc.texi,v 1.8.4.20 2002/02/11 15:59:18 guus Exp $
+$Id: tinc.texi,v 1.8.4.21 2002/02/18 16:25:15 guus Exp $
 
 Permission is granted to make and distribute verbatim copies of this
 manual provided the copyright notice and this permission notice are
@@ -43,7 +43,7 @@ Copyright @copyright{} 1998-2002 Ivo Timmermans
 <itimmermans@@bigfoot.com>, Guus Sliepen <guus@@sliepen.warande.net> and
 Wessel Dankers <wsl@@nl.linux.org>.
 
-$Id: tinc.texi,v 1.8.4.20 2002/02/11 15:59:18 guus Exp $
+$Id: tinc.texi,v 1.8.4.21 2002/02/18 16:25:15 guus Exp $
 
 Permission is granted to make and distribute verbatim copies of this
 manual provided the copyright notice and this permission notice are
@@ -736,6 +736,12 @@ required directives are given in @strong{bold}.
 @subsection Main configuration variables
 
 @table @asis
+@cindex AddressFamily
+@item AddressFamily = <ipv4|ipv6|any> (ipv4)
+This option affects the address family of listening and outgoing sockets.
+If "any" is selected, then the listening sockets will be IPv6 sockets,
+but on most platforms those will also accept IPv4 connections.
+
 @cindex BindToInterface
 @item BindToInterface = <interface>
 If you have more than one network interface in your computer, tinc will
index 05a120125c1a21166a6e51f60d2f2dc4d5e98873..4e52a3ae305ae49b0a855c16757ad955c6470213 100644 (file)
@@ -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
index 776e36d1c368a2ce478795b187d30dd0cc20bfd3..15b0de2e39e37ef6ed45b99725d507fb2f24541c 100644 (file)
--- 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 <guus@sliepen.warande.net>\n"
 "Language-Team: Dutch <vertaling@nl.linux.org>\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"
index 7ea85a15227d21c8001654fa32edcf5c185746d1..d769071c1c0b78aac5a76528a6f520a48ba3e40b 100644 (file)
@@ -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
 
index fc8237201cba67075f3aed67836fecd29818d079..3bf9b85f602ca815e77f4d2d86ec1a6498bbfd75 100644 (file)
@@ -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. */
index a04d6687d81ec5936c3772c44448a69bb4adbe38..bf399ddba90866166f2886336886ccb0fe29703d 100644 (file)
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-    $Id: conf.h,v 1.6.4.31 2002/02/10 21:57:53 guus Exp $
+    $Id: conf.h,v 1.6.4.32 2002/02/18 16:25:16 guus Exp $
 */
 
 #ifndef __TINC_CONF_H__
 #define __TINC_CONF_H__
 
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+
 #include <avl_tree.h>
 #include "net.h"
 #include "subnet.h"
@@ -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 **);
 
index 815de4ba29a914816a1c0cb685d9393fad58297e..8620e4afd577310356adc4e369fa9d54be679ecf 100644 (file)
@@ -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."));
index 1689aee35d551ab1cba2f5eb4bd281f8d137e69d..436f192a91636bdc24727bd6b0de1a273aa65f2f 100644 (file)
@@ -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 *);
 
index 1851f51f8b9b5d5aa1b91143c3f236d9a2e1cf00..b834879e2aa506a49f60f552220edbeec1d4d267 100644 (file)
@@ -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
 }
index 9a60af652a645d6ddb304e4c616632b94bc1fa8a..e3fa078ab6f43f312552fb86e10e0faa65ffea5f 100644 (file)
@@ -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__
 
 #include <avl_tree.h>
 
+#include "net.h"
 #include "node.h"
 #include "connection.h"
 
 typedef struct halfconnection_t {
   struct node_t *node;             /* node associated with this end of the connection */
-
-  ipv4_t address;                  /* real (internet) ip on this end of the meta connection */
-  port_t port;                     /* port number of this end of the meta connection */
+  sockaddr_t tcpaddress;           /* real (internet) ip on this end of the meta connection */
+  sockaddr_t udpaddress;           /* real (internet) ip on this end of the vpn connection */
 } halfconnection_t;
 
 typedef struct edge_t {
index e75076a99d3da25a01e502981ce5ba0c08b8d4ec..2f5f32e20bba0510f51f37e65d39ca49afa89a4d 100644 (file)
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-    $Id: device.c,v 1.1.2.3 2002/02/11 12:33:01 guus Exp $
+    $Id: device.c,v 1.1.2.4 2002/02/18 16:25:19 guus Exp $
 */
 
 #include "config.h"
 
 #include <stdio.h>
+#include <errno.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/ioctl.h>
@@ -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;
     }
 
index 0847b2814e081996a52c327e445d15ced83d06be..abc918d9b1ce881cb05d56db7c545c335256ed5a 100644 (file)
@@ -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);
index 88355caabdfa80799558d55d4c6e274db9a491cf..450fcd1d601894d0ca489bf54acbf40aa7ad021d 100644 (file)
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-    $Id: device.c,v 1.1.2.6 2002/02/11 12:33:01 guus Exp $
+    $Id: device.c,v 1.1.2.7 2002/02/18 16:25:19 guus Exp $
 */
 
 #include "config.h"
 
 #include <stdio.h>
+#include <errno.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
@@ -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;
         }
     }
index e108ea1a8a9f8a63a65ef564a41445aed4ffcb35..f2326d118896cad21cc28f53de5488dbbfdcd708 100644 (file)
@@ -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;
     }
index 3328863e633d160df1cee8d6e18f096880e98136..bf58cf00faa11e87a607d4ac1de270afa3c9b589 100644 (file)
--- 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"
 #include <net/if.h>
 
 #include <openssl/rand.h>
-#include <openssl/evp.h>
-#include <openssl/pem.h>
-#include <openssl/hmac.h>
 
-#ifndef HAVE_RAND_PSEUDO_BYTES
-#define RAND_pseudo_bytes RAND_bytes
-#endif
-
-#include <zlib.h>
-
-#include <utils.h>
-#include <xalloc.h>
-#include <avl_tree.h>
-#include <list.h>
-
-#include "conf.h"
-#include "connection.h"
-#include "meta.h"
-#include "net.h"
-#include "netutl.h"
-#include "process.h"
-#include "protocol.h"
-#include "subnet.h"
-#include "graph.h"
-#include "process.h"
-#include "route.h"
-#include "device.h"
-#include "event.h"
-
-#include "system.h"
-
-int maxtimeout = 900;
-int seconds_till_retry = 5;
-
-int tcp_socket = -1;
-int udp_socket = -1;
-
-int keylifetime = 0;
-int keyexpires = 0;
-
-int do_prune = 0;
-int do_purge = 0;
-int sighup = 0;
-int sigalrm = 0;
-
-#define MAX_SEQNO 1073741824
-
-/* VPN packet I/O */
-
-void receive_udppacket(node_t *n, vpn_packet_t *inpkt)
-{
-  vpn_packet_t pkt1, pkt2;
-  vpn_packet_t *pkt[] = {&pkt1, &pkt2, &pkt1, &pkt2};
-  int nextpkt = 0;
-  vpn_packet_t *outpkt = pkt[0];
-  int outlen, outpad;
-  long int complen = MTU + 12;
-  EVP_CIPHER_CTX ctx;
-  char hmac[EVP_MAX_MD_SIZE];
-cp
-  /* Check the message authentication code */
-
-  if(myself->digest && myself->maclength)
-    {
-      inpkt->len -= myself->maclength;
-      HMAC(myself->digest, myself->key, myself->keylength, (char *)&inpkt->seqno, inpkt->len, hmac, NULL);
-      if(memcmp(hmac, (char *)&inpkt->seqno + inpkt->len, myself->maclength))
-       {
-         syslog(LOG_DEBUG, _("Got unauthenticated packet from %s (%s)"), n->name, n->hostname);
-         return;
-       }
-    }
-
-  /* Decrypt the packet */
-
-  if(myself->cipher)
-  {
-    outpkt = pkt[nextpkt++];
-
-    EVP_DecryptInit(&ctx, myself->cipher, myself->key, myself->key + myself->cipher->key_len);
-    EVP_DecryptUpdate(&ctx, (char *)&outpkt->seqno, &outlen, (char *)&inpkt->seqno, inpkt->len);
-    EVP_DecryptFinal(&ctx, (char *)&outpkt->seqno + outlen, &outpad);
-
-    outpkt->len = outlen + outpad;
-    inpkt = outpkt;
-  }
-
-  /* Check the sequence number */
-
-  inpkt->len -= sizeof(inpkt->seqno);
-  inpkt->seqno = ntohl(inpkt->seqno);
-
-  if(inpkt->seqno <= n->received_seqno)
-  {
-    syslog(LOG_DEBUG, _("Got late or replayed packet from %s (%s), seqno %d"), n->name, n->hostname, inpkt->seqno);
-    return;
-  }
-  
-  n->received_seqno = inpkt->seqno;
-
-  if(n->received_seqno > MAX_SEQNO)
-    keyexpires = 0;
-
-  /* Decompress the packet */
-  
-  if(myself->compression)
-  {
-    outpkt = pkt[nextpkt++];
-
-    if(uncompress(outpkt->data, &complen, inpkt->data, inpkt->len) != Z_OK)
-    {
-      syslog(LOG_ERR, _("Error while uncompressing packet from %s (%s)"), n->name, n->hostname);
-      return;
-    }
-    
-    outpkt->len = complen;
-    inpkt = outpkt;
-  }
-
-  receive_packet(n, inpkt);
-cp
-}
-
-void receive_tcppacket(connection_t *c, char *buffer, int len)
-{
-  vpn_packet_t outpkt;
-cp
-  outpkt.len = len;
-  memcpy(outpkt.data, buffer, len);
-
-  receive_packet(c->node, &outpkt);
-cp
-}
-
-void receive_packet(node_t *n, vpn_packet_t *packet)
-{
-cp
-  if(debug_lvl >= DEBUG_TRAFFIC)
-    syslog(LOG_DEBUG, _("Received packet of %d bytes from %s (%s)"), packet->len, n->name, n->hostname);
-
-  route_incoming(n, packet);
-cp
-}
-
-void send_udppacket(node_t *n, vpn_packet_t *inpkt)
-{
-  vpn_packet_t pkt1, pkt2;
-  vpn_packet_t *pkt[] = {&pkt1, &pkt2, &pkt1, &pkt2};
-  int nextpkt = 0;
-  vpn_packet_t *outpkt;
-  int outlen, outpad;
-  long int complen = MTU + 12;
-  EVP_CIPHER_CTX ctx;
-  struct sockaddr_in to;
-  socklen_t tolen = sizeof(to);
-  vpn_packet_t *copy;
-cp
-  if(!n->status.validkey)
-    {
-      if(debug_lvl >= DEBUG_TRAFFIC)
-       syslog(LOG_INFO, _("No valid key known yet for %s (%s), queueing packet"),
-              n->name, n->hostname);
-
-      /* Since packet is on the stack of handle_tap_input(),
-         we have to make a copy of it first. */
-
-      copy = xmalloc(sizeof(vpn_packet_t));
-      memcpy(copy, inpkt, sizeof(vpn_packet_t));
-
-      list_insert_tail(n->queue, copy);
-
-      if(!n->status.waitingforkey)
-       send_req_key(n->nexthop->connection, myself, n);
-
-      return;
-    }
-
-  /* Compress the packet */
-
-  if(n->compression)
-  {
-    outpkt = pkt[nextpkt++];
-
-    if(compress2(outpkt->data, &complen, inpkt->data, inpkt->len, n->compression) != Z_OK)
-    {
-      syslog(LOG_ERR, _("Error while compressing packet to %s (%s)"), n->name, n->hostname);
-      return;
-    }
-    
-    outpkt->len = complen;
-    inpkt = outpkt;
-  }
-
-  /* Add sequence number */
-
-  inpkt->seqno = htonl(++(n->sent_seqno));
-  inpkt->len += sizeof(inpkt->seqno);
-
-  /* Encrypt the packet */
-
-  if(n->cipher)
-  {
-    outpkt = pkt[nextpkt++];
-
-    EVP_EncryptInit(&ctx, n->cipher, n->key, n->key + n->cipher->key_len);
-    EVP_EncryptUpdate(&ctx, (char *)&outpkt->seqno, &outlen, (char *)&inpkt->seqno, inpkt->len);
-    EVP_EncryptFinal(&ctx, (char *)&outpkt->seqno + outlen, &outpad);
-
-    outpkt->len = outlen + outpad;
-    inpkt = outpkt;
-  }
-
-  /* Add the message authentication code */
-
-  if(n->digest && n->maclength)
-    {
-      HMAC(n->digest, n->key, n->keylength, (char *)&inpkt->seqno, inpkt->len, (char *)&inpkt->seqno + inpkt->len, &outlen);
-      inpkt->len += n->maclength;
-    }
-
-  /* Send the packet */
-
-  to.sin_family = AF_INET;
-  to.sin_addr.s_addr = htonl(n->address);
-  to.sin_port = htons(n->port);
-
-  if((sendto(udp_socket, (char *)&inpkt->seqno, inpkt->len, 0, (const struct sockaddr *)&to, tolen)) < 0)
-    {
-      syslog(LOG_ERR, _("Error sending packet to %s (%s): %m"),
-             n->name, n->hostname);
-      return;
-    }
-cp
-}
-
-/*
-  send a packet to the given vpn ip.
-*/
-void send_packet(node_t *n, vpn_packet_t *packet)
-{
-  node_t *via;
-cp
-  if(debug_lvl >= DEBUG_TRAFFIC)
-    syslog(LOG_ERR, _("Sending packet of %d bytes to %s (%s)"),
-           packet->len, n->name, n->hostname);
-
-  if(n == myself)
-    {
-      if(debug_lvl >= DEBUG_TRAFFIC)
-        {
-          syslog(LOG_NOTICE, _("Packet is looping back to us!"));
-        }
-
-      return;
-    }
-  if(!n->status.reachable)
-    {
-      if(debug_lvl >= DEBUG_TRAFFIC)
-       syslog(LOG_INFO, _("Node %s (%s) is not reachable"),
-              n->name, n->hostname);
-      return;
-    }
-
-  via = (n->via == myself)?n->nexthop:n->via;
-
-  if(via != n && debug_lvl >= DEBUG_TRAFFIC)
-    syslog(LOG_ERR, _("Sending packet to %s via %s (%s)"),
-           n->name, via->name, n->via->hostname);
-
-  if((myself->options | via->options) & OPTION_TCPONLY)
-    {
-      if(send_tcppacket(via->connection, packet))
-        terminate_connection(via->connection, 1);
-    }
-  else
-    send_udppacket(via, packet);
-}
-
-/* Broadcast a packet using the minimum spanning tree */
-
-void broadcast_packet(node_t *from, vpn_packet_t *packet)
-{
-  avl_node_t *node;
-  connection_t *c;
-cp
-  if(debug_lvl >= DEBUG_TRAFFIC)
-    syslog(LOG_INFO, _("Broadcasting packet of %d bytes from %s (%s)"),
-          packet->len, from->name, from->hostname);
-
-  for(node = connection_tree->head; node; node = node->next)
-    {
-      c = (connection_t *)node->data;
-      if(c->status.active && c->status.mst && c != from->nexthop->connection)
-        send_packet(c->node, packet);
-    }
-cp
-}
-
-void flush_queue(node_t *n)
-{
-  list_node_t *node, *next;
-cp
-  if(debug_lvl >= DEBUG_TRAFFIC)
-    syslog(LOG_INFO, _("Flushing queue for %s (%s)"), n->name, n->hostname);
-
-  for(node = n->queue->head; node; node = next)
-    {
-      next = node->next;
-      send_udppacket(n, (vpn_packet_t *)node->data);
-      list_delete_node(n->queue, node);
-    }
-cp
-}
-
-/* Setup sockets */
-
-int setup_listen_socket(port_t port)
-{
-  int nfd, flags;
-  struct sockaddr_in a;
-  int option;
-  ipv4_t *address;
-#ifdef HAVE_LINUX
-  char *interface;
-#endif
-cp
-  if((nfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
-    {
-      syslog(LOG_ERR, _("Creating metasocket failed: %m"));
-      return -1;
-    }
-
-  flags = fcntl(nfd, F_GETFL);
-  if(fcntl(nfd, F_SETFL, flags | O_NONBLOCK) < 0)
-    {
-      close(nfd);
-      syslog(LOG_ERR, _("System call `%s' failed: %m"),
-            "fcntl");
-      return -1;
-    }
-
-  /* Optimize TCP settings */
-
-  option = 1;
-  setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option));
-  setsockopt(nfd, SOL_SOCKET, SO_KEEPALIVE, &option, sizeof(option));
-#ifdef HAVE_LINUX
-  setsockopt(nfd, SOL_TCP, TCP_NODELAY, &option, sizeof(option));
-
-  option = IPTOS_LOWDELAY;
-  setsockopt(nfd, SOL_IP, IP_TOS, &option, sizeof(option));
-
-  if(get_config_string(lookup_config(config_tree, "BindToInterface"), &interface))
-    if(setsockopt(nfd, SOL_SOCKET, SO_BINDTODEVICE, interface, strlen(interface)))
-      {
-        close(nfd);
-        syslog(LOG_ERR, _("Can't bind to interface %s: %m"), interface);
-        return -1;
-      }
-#endif
-
-  memset(&a, 0, sizeof(a));
-  a.sin_family = AF_INET;
-  a.sin_addr.s_addr = htonl(INADDR_ANY);
-  a.sin_port = htons(port);
-
-  if(get_config_address(lookup_config(config_tree, "BindToAddress"), &address))
-    {
-      a.sin_addr.s_addr = htonl(*address);
-      free(address);
-    }
-
-  if(bind(nfd, (struct sockaddr *)&a, sizeof(struct sockaddr)))
-    {
-      close(nfd);
-      syslog(LOG_ERR, _("Can't bind to port %hd/tcp: %m"), port);
-      return -1;
-    }
-
-  if(listen(nfd, 3))
-    {
-      close(nfd);
-      syslog(LOG_ERR, _("System call `%s' failed: %m"),
-            "listen");
-      return -1;
-    }
-cp
-  return nfd;
-}
-
-int setup_vpn_in_socket(port_t port)
-{
-  int nfd, flags;
-  struct sockaddr_in a;
-  const int one = 1;
-cp
-  if((nfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
-    {
-      close(nfd);
-      syslog(LOG_ERR, _("Creating socket failed: %m"));
-      return -1;
-    }
-
-  setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
-
-  flags = fcntl(nfd, F_GETFL);
-  if(fcntl(nfd, F_SETFL, flags | O_NONBLOCK) < 0)
-    {
-      close(nfd);
-      syslog(LOG_ERR, _("System call `%s' failed: %m"),
-            "fcntl");
-      return -1;
-    }
-
-  memset(&a, 0, sizeof(a));
-  a.sin_family = AF_INET;
-  a.sin_port = htons(port);
-  a.sin_addr.s_addr = htonl(INADDR_ANY);
-
-  if(bind(nfd, (struct sockaddr *)&a, sizeof(struct sockaddr)))
-    {
-      close(nfd);
-      syslog(LOG_ERR, _("Can't bind to port %hd/udp: %m"), port);
-      return -1;
-    }
-cp
-  return nfd;
-}
-
-void retry_outgoing(outgoing_t *outgoing)
-{
-  event_t *event;
-cp
-  outgoing->timeout += 5;
-  if(outgoing->timeout > maxtimeout)
-    outgoing->timeout = maxtimeout;
-
-  event = new_event();
-  event->handler = (event_handler_t)setup_outgoing_connection;
-  event->time = time(NULL) + outgoing->timeout;
-  event->data = outgoing;
-  event_add(event);
-
-  if(debug_lvl >= DEBUG_CONNECTIONS)
-    syslog(LOG_NOTICE, _("Trying to re-establish outgoing connection in %d seconds"), outgoing->timeout);
-cp
-}
-
-int setup_outgoing_socket(connection_t *c)
-{
-  int flags;
-  struct sockaddr_in a;
-cp
-  if(debug_lvl >= DEBUG_CONNECTIONS)
-    syslog(LOG_INFO, _("Trying to connect to %s (%s)"), c->name, c->hostname);
-
-  c->socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
-
-  if(c->socket == -1)
-    {
-      syslog(LOG_ERR, _("Creating socket for %s port %d failed: %m"),
-             c->hostname, c->port);
-      return -1;
-    }
-
-  /* Bind first to get a fix on our source port???
-
-  a.sin_family = AF_INET;
-  a.sin_port = htons(0);
-  a.sin_addr.s_addr = htonl(INADDR_ANY);
-
-  if(bind(c->socket, (struct sockaddr *)&a, sizeof(struct sockaddr)))
-    {
-      close(c->socket);
-      syslog(LOG_ERR, _("System call `%s' failed: %m"), "bind");
-      return -1;
-    }
-
-  */
-
-  /* Optimize TCP settings?
-
-  option = 1;
-  setsockopt(c->socket, SOL_SOCKET, SO_KEEPALIVE, &option, sizeof(option));
-#ifdef HAVE_LINUX
-  setsockopt(c->socket, SOL_TCP, TCP_NODELAY, &option, sizeof(option));
-
-  option = IPTOS_LOWDELAY;
-  setsockopt(c->socket, SOL_IP, IP_TOS, &option, sizeof(option));
-#endif
-
-  */
-
-  /* Connect */
-
-  a.sin_family = AF_INET;
-  a.sin_port = htons(c->port);
-  a.sin_addr.s_addr = htonl(c->address);
-
-  if(connect(c->socket, (struct sockaddr *)&a, sizeof(a)) == -1)
-    {
-      close(c->socket);
-      syslog(LOG_ERR, _("%s port %hd: %m"), c->hostname, c->port);
-      return -1;
-    }
-
-  flags = fcntl(c->socket, F_GETFL);
-
-  if(fcntl(c->socket, F_SETFL, flags | O_NONBLOCK) < 0)
-    {
-      close(c->socket);
-      syslog(LOG_ERR, _("fcntl for %s port %d: %m"),
-             c->hostname, c->port);
-      return -1;
-    }
-
-  if(debug_lvl >= DEBUG_CONNECTIONS)
-    syslog(LOG_INFO, _("Connected to %s port %hd"),
-         c->hostname, c->port);
-cp
-  return 0;
-}
-
-void setup_outgoing_connection(outgoing_t *outgoing)
-{
-  connection_t *c;
-  node_t *n;
-  struct hostent *h;
-cp
-  n = lookup_node(outgoing->name);
-  
-  if(n)
-    if(n->connection)
-      {
-        if(debug_lvl >= DEBUG_CONNECTIONS)       
-          syslog(LOG_INFO, _("Already connected to %s"), outgoing->name);
-        n->connection->outgoing = outgoing;
-        return;
-      }
-
-  c = new_connection();
-  c->name = xstrdup(outgoing->name);
-
-  init_configuration(&c->config_tree);
-  read_connection_config(c);
-  
-  if(!get_config_string(lookup_config(c->config_tree, "Address"), &c->hostname))
-    {
-      syslog(LOG_ERR, _("No address specified for %s"), c->name);
-      free_connection(c);
-      free(outgoing->name);
-      free(outgoing);
-      return;
-    }
-
-  if(!get_config_port(lookup_config(c->config_tree, "Port"), &c->port))
-    c->port = 655;
-
-  if(!(h = gethostbyname(c->hostname)))
-    {
-      syslog(LOG_ERR, _("Error looking up `%s': %m"), c->hostname);
-      free_connection(c);
-      retry_outgoing(outgoing);
-      return;
-    }
-
-  c->address = ntohl(*((ipv4_t*)(h->h_addr_list[0])));
-  c->hostname = hostlookup(htonl(c->address));
-
-  if(setup_outgoing_socket(c) < 0)
-    {
-      syslog(LOG_ERR, _("Could not set up a meta connection to %s (%s)"),
-             c->name, c->hostname);
-      retry_outgoing(outgoing);
-      return;
-    }
-
-  c->outgoing = outgoing;
-  c->last_ping_time = time(NULL);
-
-  connection_add(c);
-
-  send_id(c);
-cp
-}
-
-int read_rsa_public_key(connection_t *c)
-{
-  FILE *fp;
-  char *fname;
-  char *key;
-cp
-  if(!c->rsa_key)
-    c->rsa_key = RSA_new();
-
-  /* First, check for simple PublicKey statement */
-
-  if(get_config_string(lookup_config(c->config_tree, "PublicKey"), &key))
-    {
-      BN_hex2bn(&c->rsa_key->n, key);
-      BN_hex2bn(&c->rsa_key->e, "FFFF");
-      free(key);
-      return 0;
-    }
-
-  /* Else, check for PublicKeyFile statement and read it */
-
-  if(get_config_string(lookup_config(c->config_tree, "PublicKeyFile"), &fname))
-    {
-      if(is_safe_path(fname))
-        {
-          if((fp = fopen(fname, "r")) == NULL)
-            {
-              syslog(LOG_ERR, _("Error reading RSA public key file `%s': %m"),
-                    fname);
-              free(fname);
-              return -1;
-            }
-          free(fname);
-          c->rsa_key = PEM_read_RSAPublicKey(fp, &c->rsa_key, NULL, NULL);
-          fclose(fp);
-          if(!c->rsa_key)
-            {
-              syslog(LOG_ERR, _("Reading RSA public key file `%s' failed: %m"),
-                    fname);
-              return -1;
-            }
-          return 0;
-        }
-      else
-        {
-          free(fname);
-          return -1;
-       }
-    }
-
-  /* Else, check if a harnessed public key is in the config file */
-
-  asprintf(&fname, "%s/hosts/%s", confbase, c->name);
-  if((fp = fopen(fname, "r")))
-    {
-      c->rsa_key = PEM_read_RSAPublicKey(fp, &c->rsa_key, NULL, NULL);
-      fclose(fp);
-    }
-
-  free(fname);
-
-  if(c->rsa_key)
-    return 0;
-  else
-    {
-      syslog(LOG_ERR, _("No public key for %s specified!"), c->name);
-      return -1;
-    }
-}
-
-int read_rsa_private_key(void)
-{
-  FILE *fp;
-  char *fname, *key;
-cp
-  if(get_config_string(lookup_config(config_tree, "PrivateKey"), &key))
-    {
-      myself->connection->rsa_key = RSA_new();
-      BN_hex2bn(&myself->connection->rsa_key->d, key);
-      BN_hex2bn(&myself->connection->rsa_key->e, "FFFF");
-      free(key);
-      return 0;
-    }
-
-  if(!get_config_string(lookup_config(config_tree, "PrivateKeyFile"), &fname))
-    asprintf(&fname, "%s/rsa_key.priv", confbase);
-
-  if(is_safe_path(fname))
-    {
-      if((fp = fopen(fname, "r")) == NULL)
-        {
-          syslog(LOG_ERR, _("Error reading RSA private key file `%s': %m"),
-                fname);
-          free(fname);
-          return -1;
-        }
-      free(fname);
-      myself->connection->rsa_key = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
-      fclose(fp);
-      if(!myself->connection->rsa_key)
-        {
-          syslog(LOG_ERR, _("Reading RSA private key file `%s' failed: %m"),
-                fname);
-          return -1;
-        }
-      return 0;
-    }
-
-  free(fname);
-  return -1;
-}
-
-int check_rsa_key(RSA *rsa_key)
-{
-  char *test1, *test2, *test3;
-cp
-  if(rsa_key->p && rsa_key->q)
-    {
-      if(RSA_check_key(rsa_key) != 1)
-         return -1;
-    }
-  else
-    {
-      test1 = xmalloc(RSA_size(rsa_key));
-      test2 = xmalloc(RSA_size(rsa_key));
-      test3 = xmalloc(RSA_size(rsa_key));
-
-      if(RSA_public_encrypt(RSA_size(rsa_key), test1, test2, rsa_key, RSA_NO_PADDING) != RSA_size(rsa_key))
-         return -1;
-
-      if(RSA_private_decrypt(RSA_size(rsa_key), test2, test3, rsa_key, RSA_NO_PADDING) != RSA_size(rsa_key))
-         return -1;
-
-      if(memcmp(test1, test3, RSA_size(rsa_key)))
-         return -1;
-    }
-cp
-  return 0;
-}
-
-/*
-  Configure node_t myself and set up the local sockets (listen only)
-*/
-int setup_myself(void)
-{
-  config_t *cfg;
-  subnet_t *subnet;
-  char *name, *mode, *cipher, *digest;
-  int choice;
-cp
-  myself = new_node();
-  myself->connection = new_connection();
-  init_configuration(&myself->connection->config_tree);
-
-  asprintf(&myself->hostname, _("MYSELF"));
-  asprintf(&myself->connection->hostname, _("MYSELF"));
-
-  myself->connection->options = 0;
-  myself->connection->protocol_version = PROT_CURRENT;
-
-  if(!get_config_string(lookup_config(config_tree, "Name"), &name)) /* Not acceptable */
-    {
-      syslog(LOG_ERR, _("Name for tinc daemon required!"));
-      return -1;
-    }
-
-  if(check_id(name))
-    {
-      syslog(LOG_ERR, _("Invalid name for myself!"));
-      free(name);
-      return -1;
-    }
-
-  myself->name = name;
-  myself->connection->name = xstrdup(name);
-
-cp
-  if(read_rsa_private_key())
-    return -1;
-
-  if(read_connection_config(myself->connection))
-    {
-      syslog(LOG_ERR, _("Cannot open host configuration file for myself!"));
-      return -1;
-    }
-
-  if(read_rsa_public_key(myself->connection))
-    return -1;
-cp
-
-  if(check_rsa_key(myself->connection->rsa_key))
-    {
-      syslog(LOG_ERR, _("Invalid public/private keypair!"));
-      return -1;
-    }
-
-  if(!get_config_port(lookup_config(myself->connection->config_tree, "Port"), &myself->port))
-    myself->port = 655;
-
-  myself->connection->port = myself->port;
-
-/* Read in all the subnets specified in the host configuration file */
-
-  cfg = lookup_config(myself->connection->config_tree, "Subnet");
-
-  while(cfg)
-    {
-      if(!get_config_subnet(cfg, &subnet))
-        return -1;
-
-      subnet_add(myself, subnet);
-
-      cfg = lookup_config_next(myself->connection->config_tree, cfg);
-    }
-
-cp
-  /* Check some options */
-
-  if(get_config_bool(lookup_config(config_tree, "IndirectData"), &choice))
-    if(choice)
-      myself->options |= OPTION_INDIRECT;
-
-  if(get_config_bool(lookup_config(config_tree, "TCPOnly"), &choice))
-    if(choice)
-      myself->options |= OPTION_TCPONLY;
-
-  if(get_config_bool(lookup_config(myself->connection->config_tree, "IndirectData"), &choice))
-    if(choice)
-      myself->options |= OPTION_INDIRECT;
-
-  if(get_config_bool(lookup_config(myself->connection->config_tree, "TCPOnly"), &choice))
-    if(choice)
-      myself->options |= OPTION_TCPONLY;
-
-  if(myself->options & OPTION_TCPONLY)
-    myself->options |= OPTION_INDIRECT;
-
-  if(get_config_string(lookup_config(config_tree, "Mode"), &mode))
-    {
-      if(!strcasecmp(mode, "router"))
-        routing_mode = RMODE_ROUTER;
-      else if (!strcasecmp(mode, "switch"))
-        routing_mode = RMODE_SWITCH;
-      else if (!strcasecmp(mode, "hub"))
-        routing_mode = RMODE_HUB;
-      else
-        {
-          syslog(LOG_ERR, _("Invalid routing mode!"));
-          return -1;
-        }
-    }
-  else
-    routing_mode = RMODE_ROUTER;
-
-cp
-  /* Open sockets */
-  
-  if((tcp_socket = setup_listen_socket(myself->port)) < 0)
-    {
-      syslog(LOG_ERR, _("Unable to set up a listening TCP socket!"));
-      return -1;
-    }
-
-  if((udp_socket = setup_vpn_in_socket(myself->port)) < 0)
-    {
-      syslog(LOG_ERR, _("Unable to set up a listening UDP socket!"));
-      return -1;
-    }
-cp
-  /* Generate packet encryption key */
-
-  if(get_config_string(lookup_config(myself->connection->config_tree, "Cipher"), &cipher))
-    {
-      if(!strcasecmp(cipher, "none"))
-        {
-         myself->cipher = NULL;
-       }
-      else
-        {
-         if(!(myself->cipher = EVP_get_cipherbyname(cipher)))
-            {
-             syslog(LOG_ERR, _("Unrecognized cipher type!"));
-             return -1;
-           }
-        }
-    }
-  else
-    myself->cipher = EVP_bf_cbc();
-
-  if(myself->cipher)
-    myself->keylength = myself->cipher->key_len + myself->cipher->iv_len;
-  else
-    myself->keylength = 1;
-
-  myself->key = (char *)xmalloc(myself->keylength);
-  RAND_pseudo_bytes(myself->key, myself->keylength);
-
-  if(!get_config_int(lookup_config(config_tree, "KeyExpire"), &keylifetime))
-    keylifetime = 3600;
-
-  keyexpires = time(NULL) + keylifetime;
-
-  /* Check if we want to use message authentication codes... */
-
-  if(get_config_string(lookup_config(myself->connection->config_tree, "Digest"), &digest))
-    {
-      if(!strcasecmp(digest, "none"))
-        {
-         myself->digest = NULL;
-       }
-      else
-        {
-          if(!(myself->digest = EVP_get_digestbyname(digest)))
-           {
-             syslog(LOG_ERR, _("Unrecognized digest type!"));
-             return -1;
-            }
-       }
-    }
-  else
-    myself->digest = EVP_sha1();
-
-  if(get_config_int(lookup_config(myself->connection->config_tree, "MACLength"), &myself->maclength))
-    {
-      if(myself->digest)
-        {
-         if(myself->maclength > myself->digest->md_size)
-            {
-             syslog(LOG_ERR, _("MAC length exceeds size of digest!"));
-             return -1;
-           }
-         else if (myself->maclength < 0)
-            {
-             syslog(LOG_ERR, _("Bogus MAC length!"));
-             return -1;
-           }
-        }
-    }
-  else
-    myself->maclength = 4;
-
-  /* Compression */
-
-  if(get_config_int(lookup_config(myself->connection->config_tree, "Compression"), &myself->compression))
-    {
-      if(myself->compression < 0 || myself->compression > 9)
-        {
-         syslog(LOG_ERR, _("Bogus compression level!"));
-         return -1;
-       }
-    }
-  else
-    myself->compression = 0;
-cp
-  /* Done */
-
-  myself->nexthop = myself;
-  myself->via = myself;
-  myself->status.active = 1;
-  node_add(myself);
-
-  graph();
-
-  syslog(LOG_NOTICE, _("Ready: listening on port %hd"), myself->port);
-cp
-  return 0;
-}
-
-/*
-  setup all initial network connections
-*/
-int setup_network_connections(void)
-{
-cp
-  init_connections();
-  init_subnets();
-  init_nodes();
-  init_edges();
-  init_events();
-
-  if(get_config_int(lookup_config(config_tree, "PingTimeout"), &pingtimeout))
-    {
-      if(pingtimeout < 1)
-        {
-          pingtimeout = 86400;
-        }
-    }
-  else
-    pingtimeout = 60;
-
-  if(setup_device() < 0)
-    return -1;
-
-  /* Run tinc-up script to further initialize the tap interface */
-  execute_script("tinc-up");
-
-  if(setup_myself() < 0)
-    return -1;
-
-  try_outgoing_connections();
-cp
-  return 0;
-}
-
-/*
-  close all open network connections
-*/
-void close_network_connections(void)
-{
-  avl_node_t *node, *next;
-  connection_t *c;
-cp
-  for(node = connection_tree->head; node; node = next)
-    {
-      next = node->next;
-      c = (connection_t *)node->data;
-      if(c->outgoing)
-        free(c->outgoing->name), free(c->outgoing);
-      terminate_connection(c, 0);
-    }
-
-  if(myself && myself->connection)
-    terminate_connection(myself->connection, 0);
-
-  close(udp_socket);
-  close(tcp_socket);
-
-  exit_events();
-  exit_edges();
-  exit_subnets();
-  exit_nodes();
-  exit_connections();
-
-  execute_script("tinc-down");
-
-  close_device();
-cp
-  return;
-}
-
-/*
-  handle an incoming tcp connect call and open
-  a connection to it.
-*/
-connection_t *create_new_connection(int sfd)
-{
-  connection_t *c;
-  struct sockaddr_in ci;
-  int len = sizeof(ci);
-cp
-  c = new_connection();
-
-  if(getpeername(sfd, (struct sockaddr *) &ci, (socklen_t *) &len) < 0)
-    {
-      syslog(LOG_ERR, _("System call `%s' failed: %m"),
-            "getpeername");
-      close(sfd);
-      return NULL;
-    }
+#include <utils.h>
+#include <xalloc.h>
+#include <avl_tree.h>
+#include <list.h>
 
-  c->address = ntohl(ci.sin_addr.s_addr);
-  c->hostname = hostlookup(ci.sin_addr.s_addr);
-  c->port = htons(ci.sin_port);
-  c->socket = sfd;
-  c->last_ping_time = time(NULL);
+#include "conf.h"
+#include "connection.h"
+#include "meta.h"
+#include "net.h"
+#include "netutl.h"
+#include "process.h"
+#include "protocol.h"
+#include "subnet.h"
+#include "graph.h"
+#include "process.h"
+#include "route.h"
+#include "device.h"
+#include "event.h"
 
-  if(debug_lvl >= DEBUG_CONNECTIONS)
-    syslog(LOG_NOTICE, _("Connection from %s port %d"),
-         c->hostname, c->port);
+#include "system.h"
 
-  c->allow_request = ID;
-cp
-  return c;
-}
+int do_prune = 0;
+int do_purge = 0;
+int sighup = 0;
+int sigalrm = 0;
 
 /*
   put all file descriptors in an fd_set array
@@ -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
index 93ac391e4e7883116bade65b247145c2d673ebae..1100071a5c012ba4d595d4e6c1970e74be0b7df1 100644 (file)
--- a/src/net.h
+++ b/src/net.h
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-    $Id: net.h,v 1.9.4.38 2002/02/10 21:57:54 guus Exp $
+    $Id: net.h,v 1.9.4.39 2002/02/18 16:25:16 guus Exp $
 */
 
 #ifndef __TINC_NET_H__
 #define __TINC_NET_H__
 
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
 #include <sys/time.h>
 
 #include "config.h"
@@ -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 (file)
index 0000000..5171a4f
--- /dev/null
@@ -0,0 +1,391 @@
+/*
+    net_packet.c -- Handles in- and outgoing VPN packets
+    Copyright (C) 1998-2002 Ivo Timmermans <itimmermans@bigfoot.com>,
+                  2000-2002 Guus Sliepen <guus@sliepen.warande.net>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+    $Id: net_packet.c,v 1.1.2.1 2002/02/18 16:25:16 guus Exp $
+*/
+
+#include "config.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#ifdef HAVE_LINUX
+ #include <netinet/ip.h>
+ #include <netinet/tcp.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+/* SunOS really wants sys/socket.h BEFORE net/if.h,
+   and FreeBSD wants these lines below the rest. */
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#include <openssl/rand.h>
+#include <openssl/evp.h>
+#include <openssl/pem.h>
+#include <openssl/hmac.h>
+
+#ifndef HAVE_RAND_PSEUDO_BYTES
+#define RAND_pseudo_bytes RAND_bytes
+#endif
+
+#include <zlib.h>
+
+#include <utils.h>
+#include <xalloc.h>
+#include <avl_tree.h>
+#include <list.h>
+
+#include "conf.h"
+#include "connection.h"
+#include "meta.h"
+#include "net.h"
+#include "netutl.h"
+#include "process.h"
+#include "protocol.h"
+#include "subnet.h"
+#include "graph.h"
+#include "process.h"
+#include "route.h"
+#include "device.h"
+#include "event.h"
+
+#include "system.h"
+
+int keylifetime = 0;
+int keyexpires = 0;
+
+#define MAX_SEQNO 1073741824
+
+/* VPN packet I/O */
+
+void receive_udppacket(node_t *n, vpn_packet_t *inpkt)
+{
+  vpn_packet_t pkt1, pkt2;
+  vpn_packet_t *pkt[] = {&pkt1, &pkt2, &pkt1, &pkt2};
+  int nextpkt = 0;
+  vpn_packet_t *outpkt = pkt[0];
+  int outlen, outpad;
+  long int complen = MTU + 12;
+  EVP_CIPHER_CTX ctx;
+  char hmac[EVP_MAX_MD_SIZE];
+cp
+  /* Check the message authentication code */
+
+  if(myself->digest && myself->maclength)
+    {
+      inpkt->len -= myself->maclength;
+      HMAC(myself->digest, myself->key, myself->keylength, (char *)&inpkt->seqno, inpkt->len, hmac, NULL);
+      if(memcmp(hmac, (char *)&inpkt->seqno + inpkt->len, myself->maclength))
+        {
+          syslog(LOG_DEBUG, _("Got unauthenticated packet from %s (%s)"), n->name, n->hostname);
+          return;
+        }
+    }
+
+  /* Decrypt the packet */
+
+  if(myself->cipher)
+  {
+    outpkt = pkt[nextpkt++];
+
+    EVP_DecryptInit(&ctx, myself->cipher, myself->key, myself->key + myself->cipher->key_len);
+    EVP_DecryptUpdate(&ctx, (char *)&outpkt->seqno, &outlen, (char *)&inpkt->seqno, inpkt->len);
+    EVP_DecryptFinal(&ctx, (char *)&outpkt->seqno + outlen, &outpad);
+
+    outpkt->len = outlen + outpad;
+    inpkt = outpkt;
+  }
+
+  /* Check the sequence number */
+
+  inpkt->len -= sizeof(inpkt->seqno);
+  inpkt->seqno = ntohl(inpkt->seqno);
+
+  if(inpkt->seqno <= n->received_seqno)
+  {
+    syslog(LOG_DEBUG, _("Got late or replayed packet from %s (%s), seqno %d"), n->name, n->hostname, inpkt->seqno);
+    return;
+  }
+  
+  n->received_seqno = inpkt->seqno;
+
+  if(n->received_seqno > MAX_SEQNO)
+    keyexpires = 0;
+
+  /* Decompress the packet */
+  
+  if(myself->compression)
+  {
+    outpkt = pkt[nextpkt++];
+
+    if(uncompress(outpkt->data, &complen, inpkt->data, inpkt->len) != Z_OK)
+    {
+      syslog(LOG_ERR, _("Error while uncompressing packet from %s (%s)"), n->name, n->hostname);
+      return;
+    }
+    
+    outpkt->len = complen;
+    inpkt = outpkt;
+  }
+
+  receive_packet(n, inpkt);
+cp
+}
+
+void receive_tcppacket(connection_t *c, char *buffer, int len)
+{
+  vpn_packet_t outpkt;
+cp
+  outpkt.len = len;
+  memcpy(outpkt.data, buffer, len);
+
+  receive_packet(c->node, &outpkt);
+cp
+}
+
+void receive_packet(node_t *n, vpn_packet_t *packet)
+{
+cp
+  if(debug_lvl >= DEBUG_TRAFFIC)
+    syslog(LOG_DEBUG, _("Received packet of %d bytes from %s (%s)"), packet->len, n->name, n->hostname);
+
+  route_incoming(n, packet);
+cp
+}
+
+void send_udppacket(node_t *n, vpn_packet_t *inpkt)
+{
+  vpn_packet_t pkt1, pkt2;
+  vpn_packet_t *pkt[] = {&pkt1, &pkt2, &pkt1, &pkt2};
+  int nextpkt = 0;
+  vpn_packet_t *outpkt;
+  int outlen, outpad;
+  long int complen = MTU + 12;
+  EVP_CIPHER_CTX ctx;
+  vpn_packet_t *copy;
+cp
+  if(!n->status.validkey)
+    {
+      if(debug_lvl >= DEBUG_TRAFFIC)
+        syslog(LOG_INFO, _("No valid key known yet for %s (%s), queueing packet"),
+               n->name, n->hostname);
+
+      /* Since packet is on the stack of handle_tap_input(),
+         we have to make a copy of it first. */
+
+      copy = xmalloc(sizeof(vpn_packet_t));
+      memcpy(copy, inpkt, sizeof(vpn_packet_t));
+
+      list_insert_tail(n->queue, copy);
+
+      if(!n->status.waitingforkey)
+        send_req_key(n->nexthop->connection, myself, n);
+
+      return;
+    }
+
+  /* Compress the packet */
+
+  if(n->compression)
+  {
+    outpkt = pkt[nextpkt++];
+
+    if(compress2(outpkt->data, &complen, inpkt->data, inpkt->len, n->compression) != Z_OK)
+    {
+      syslog(LOG_ERR, _("Error while compressing packet to %s (%s)"), n->name, n->hostname);
+      return;
+    }
+    
+    outpkt->len = complen;
+    inpkt = outpkt;
+  }
+
+  /* Add sequence number */
+
+  inpkt->seqno = htonl(++(n->sent_seqno));
+  inpkt->len += sizeof(inpkt->seqno);
+
+  /* Encrypt the packet */
+
+  if(n->cipher)
+  {
+    outpkt = pkt[nextpkt++];
+
+    EVP_EncryptInit(&ctx, n->cipher, n->key, n->key + n->cipher->key_len);
+    EVP_EncryptUpdate(&ctx, (char *)&outpkt->seqno, &outlen, (char *)&inpkt->seqno, inpkt->len);
+    EVP_EncryptFinal(&ctx, (char *)&outpkt->seqno + outlen, &outpad);
+
+    outpkt->len = outlen + outpad;
+    inpkt = outpkt;
+  }
+
+  /* Add the message authentication code */
+
+  if(n->digest && n->maclength)
+    {
+      HMAC(n->digest, n->key, n->keylength, (char *)&inpkt->seqno, inpkt->len, (char *)&inpkt->seqno + inpkt->len, &outlen);
+      inpkt->len += n->maclength;
+    }
+
+  /* Send the packet */
+
+  if((sendto(udp_socket, (char *)&inpkt->seqno, inpkt->len, 0, &(n->address.sa), sizeof(sockaddr_t))) < 0)
+    {
+      syslog(LOG_ERR, _("Error sending packet to %s (%s): %s"),
+             n->name, n->hostname, strerror(errno));
+      return;
+    }
+cp
+}
+
+/*
+  send a packet to the given vpn ip.
+*/
+void send_packet(node_t *n, vpn_packet_t *packet)
+{
+  node_t *via;
+cp
+  if(debug_lvl >= DEBUG_TRAFFIC)
+    syslog(LOG_ERR, _("Sending packet of %d bytes to %s (%s)"),
+           packet->len, n->name, n->hostname);
+
+  if(n == myself)
+    {
+      if(debug_lvl >= DEBUG_TRAFFIC)
+        {
+          syslog(LOG_NOTICE, _("Packet is looping back to us!"));
+        }
+
+      return;
+    }
+  if(!n->status.reachable)
+    {
+      if(debug_lvl >= DEBUG_TRAFFIC)
+        syslog(LOG_INFO, _("Node %s (%s) is not reachable"),
+               n->name, n->hostname);
+      return;
+    }
+
+  via = (n->via == myself)?n->nexthop:n->via;
+
+  if(via != n && debug_lvl >= DEBUG_TRAFFIC)
+    syslog(LOG_ERR, _("Sending packet to %s via %s (%s)"),
+           n->name, via->name, n->via->hostname);
+
+  if((myself->options | via->options) & OPTION_TCPONLY)
+    {
+      if(send_tcppacket(via->connection, packet))
+        terminate_connection(via->connection, 1);
+    }
+  else
+    send_udppacket(via, packet);
+}
+
+/* Broadcast a packet using the minimum spanning tree */
+
+void broadcast_packet(node_t *from, vpn_packet_t *packet)
+{
+  avl_node_t *node;
+  connection_t *c;
+cp
+  if(debug_lvl >= DEBUG_TRAFFIC)
+    syslog(LOG_INFO, _("Broadcasting packet of %d bytes from %s (%s)"),
+           packet->len, from->name, from->hostname);
+
+  for(node = connection_tree->head; node; node = node->next)
+    {
+      c = (connection_t *)node->data;
+      if(c->status.active && c->status.mst && c != from->nexthop->connection)
+        send_packet(c->node, packet);
+    }
+cp
+}
+
+void flush_queue(node_t *n)
+{
+  list_node_t *node, *next;
+cp
+  if(debug_lvl >= DEBUG_TRAFFIC)
+    syslog(LOG_INFO, _("Flushing queue for %s (%s)"), n->name, n->hostname);
+
+  for(node = n->queue->head; node; node = next)
+    {
+      next = node->next;
+      send_udppacket(n, (vpn_packet_t *)node->data);
+      list_delete_node(n->queue, node);
+    }
+cp
+}
+
+void handle_incoming_vpn_data(void)
+{
+  vpn_packet_t pkt;
+  int x, l = sizeof(x);
+  char *hostname;
+  sockaddr_t from;
+  socklen_t fromlen = sizeof(from);
+  node_t *n;
+cp
+  if(getsockopt(udp_socket, SOL_SOCKET, SO_ERROR, &x, &l) < 0)
+    {
+      syslog(LOG_ERR, _("This is a bug: %s:%d: %d:%s"),
+             __FILE__, __LINE__, udp_socket, strerror(errno));
+      return;
+    }
+  if(x)
+    {
+      syslog(LOG_ERR, _("Incoming data socket error: %s"), strerror(x));
+      return;
+    }
+
+  if((pkt.len = recvfrom(udp_socket, (char *)&pkt.seqno, MAXSIZE, 0, &from.sa, &fromlen)) <= 0)
+    {
+      syslog(LOG_ERR, _("Receiving packet failed: %s"), strerror(errno));
+      return;
+    }
+
+  n = lookup_node_udp(&from);
+
+  if(!n)
+    {
+      hostname = sockaddr2hostname(&from);
+      syslog(LOG_WARNING, _("Received UDP packet from unknown source %s"), hostname);
+      free(hostname);
+      return;
+    }
+
+/*
+  if(n->connection)
+    n->connection->last_ping_time = time(NULL);
+*/
+  receive_udppacket(n, &pkt);
+cp
+}
+
diff --git a/src/net_setup.c b/src/net_setup.c
new file mode 100644 (file)
index 0000000..1c5ff15
--- /dev/null
@@ -0,0 +1,557 @@
+/*
+    net_setup.c -- Setup.
+    Copyright (C) 1998-2002 Ivo Timmermans <itimmermans@bigfoot.com>,
+                  2000-2002 Guus Sliepen <guus@sliepen.warande.net>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+    $Id: net_setup.c,v 1.1.2.1 2002/02/18 16:25:16 guus Exp $
+*/
+
+#include "config.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#ifdef HAVE_LINUX
+ #include <netinet/ip.h>
+ #include <netinet/tcp.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+/* SunOS really wants sys/socket.h BEFORE net/if.h,
+   and FreeBSD wants these lines below the rest. */
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#include <openssl/pem.h>
+#include <openssl/rsa.h>
+#include <openssl/rand.h>
+
+#include <utils.h>
+#include <xalloc.h>
+#include <avl_tree.h>
+#include <list.h>
+
+#include "conf.h"
+#include "connection.h"
+#include "meta.h"
+#include "net.h"
+#include "netutl.h"
+#include "process.h"
+#include "protocol.h"
+#include "subnet.h"
+#include "graph.h"
+#include "process.h"
+#include "route.h"
+#include "device.h"
+#include "event.h"
+
+#include "system.h"
+
+char *myport;
+
+int read_rsa_public_key(connection_t *c)
+{
+  FILE *fp;
+  char *fname;
+  char *key;
+cp
+  if(!c->rsa_key)
+    c->rsa_key = RSA_new();
+
+  /* First, check for simple PublicKey statement */
+
+  if(get_config_string(lookup_config(c->config_tree, "PublicKey"), &key))
+    {
+      BN_hex2bn(&c->rsa_key->n, key);
+      BN_hex2bn(&c->rsa_key->e, "FFFF");
+      free(key);
+      return 0;
+    }
+
+  /* Else, check for PublicKeyFile statement and read it */
+
+  if(get_config_string(lookup_config(c->config_tree, "PublicKeyFile"), &fname))
+    {
+      if(is_safe_path(fname))
+        {
+          if((fp = fopen(fname, "r")) == NULL)
+            {
+              syslog(LOG_ERR, _("Error reading RSA public key file `%s': %s"),
+                     fname, strerror(errno));
+              free(fname);
+              return -1;
+            }
+          free(fname);
+          c->rsa_key = PEM_read_RSAPublicKey(fp, &c->rsa_key, NULL, NULL);
+          fclose(fp);
+          if(!c->rsa_key)
+            {
+              syslog(LOG_ERR, _("Reading RSA public key file `%s' failed: %s"),
+                     fname, strerror(errno));
+              return -1;
+            }
+          return 0;
+        }
+      else
+        {
+          free(fname);
+          return -1;
+        }
+    }
+
+  /* Else, check if a harnessed public key is in the config file */
+
+  asprintf(&fname, "%s/hosts/%s", confbase, c->name);
+  if((fp = fopen(fname, "r")))
+    {
+      c->rsa_key = PEM_read_RSAPublicKey(fp, &c->rsa_key, NULL, NULL);
+      fclose(fp);
+    }
+
+  free(fname);
+
+  if(c->rsa_key)
+    return 0;
+  else
+    {
+      syslog(LOG_ERR, _("No public key for %s specified!"), c->name);
+      return -1;
+    }
+}
+
+int read_rsa_private_key(void)
+{
+  FILE *fp;
+  char *fname, *key;
+cp
+  if(get_config_string(lookup_config(config_tree, "PrivateKey"), &key))
+    {
+      myself->connection->rsa_key = RSA_new();
+      BN_hex2bn(&myself->connection->rsa_key->d, key);
+      BN_hex2bn(&myself->connection->rsa_key->e, "FFFF");
+      free(key);
+      return 0;
+    }
+
+  if(!get_config_string(lookup_config(config_tree, "PrivateKeyFile"), &fname))
+    asprintf(&fname, "%s/rsa_key.priv", confbase);
+
+  if(is_safe_path(fname))
+    {
+      if((fp = fopen(fname, "r")) == NULL)
+        {
+          syslog(LOG_ERR, _("Error reading RSA private key file `%s': %s"),
+                 fname, strerror(errno));
+          free(fname);
+          return -1;
+        }
+      free(fname);
+      myself->connection->rsa_key = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
+      fclose(fp);
+      if(!myself->connection->rsa_key)
+        {
+          syslog(LOG_ERR, _("Reading RSA private key file `%s' failed: %s"),
+                 fname, strerror(errno));
+          return -1;
+        }
+      return 0;
+    }
+
+  free(fname);
+  return -1;
+}
+
+int check_rsa_key(RSA *rsa_key)
+{
+  char *test1, *test2, *test3;
+cp
+  if(rsa_key->p && rsa_key->q)
+    {
+      if(RSA_check_key(rsa_key) != 1)
+          return -1;
+    }
+  else
+    {
+      test1 = xmalloc(RSA_size(rsa_key));
+      test2 = xmalloc(RSA_size(rsa_key));
+      test3 = xmalloc(RSA_size(rsa_key));
+
+      if(RSA_public_encrypt(RSA_size(rsa_key), test1, test2, rsa_key, RSA_NO_PADDING) != RSA_size(rsa_key))
+          return -1;
+
+      if(RSA_private_decrypt(RSA_size(rsa_key), test2, test3, rsa_key, RSA_NO_PADDING) != RSA_size(rsa_key))
+          return -1;
+
+      if(memcmp(test1, test3, RSA_size(rsa_key)))
+          return -1;
+    }
+cp
+  return 0;
+}
+
+/*
+  Configure node_t myself and set up the local sockets (listen only)
+*/
+int setup_myself(void)
+{
+  config_t *cfg;
+  subnet_t *subnet;
+  char *name, *mode, *afname, *cipher, *digest;
+  struct addrinfo hint, *ai;
+  int choice;
+cp
+  myself = new_node();
+  myself->connection = new_connection();
+  init_configuration(&myself->connection->config_tree);
+
+  asprintf(&myself->hostname, _("MYSELF"));
+  asprintf(&myself->connection->hostname, _("MYSELF"));
+
+  myself->connection->options = 0;
+  myself->connection->protocol_version = PROT_CURRENT;
+
+  if(!get_config_string(lookup_config(config_tree, "Name"), &name)) /* Not acceptable */
+    {
+      syslog(LOG_ERR, _("Name for tinc daemon required!"));
+      return -1;
+    }
+
+  if(check_id(name))
+    {
+      syslog(LOG_ERR, _("Invalid name for myself!"));
+      free(name);
+      return -1;
+    }
+
+  myself->name = name;
+  myself->connection->name = xstrdup(name);
+
+cp
+  if(read_rsa_private_key())
+    return -1;
+
+  if(read_connection_config(myself->connection))
+    {
+      syslog(LOG_ERR, _("Cannot open host configuration file for myself!"));
+      return -1;
+    }
+
+  if(read_rsa_public_key(myself->connection))
+    return -1;
+cp
+
+  if(check_rsa_key(myself->connection->rsa_key))
+    {
+      syslog(LOG_ERR, _("Invalid public/private keypair!"));
+      return -1;
+    }
+
+  if(!get_config_string(lookup_config(myself->connection->config_tree, "Port"), &myport))
+    asprintf(&myport, "655");
+
+/* Read in all the subnets specified in the host configuration file */
+
+  cfg = lookup_config(myself->connection->config_tree, "Subnet");
+
+  while(cfg)
+    {
+      if(!get_config_subnet(cfg, &subnet))
+        return -1;
+
+      subnet_add(myself, subnet);
+
+      cfg = lookup_config_next(myself->connection->config_tree, cfg);
+    }
+
+cp
+  /* Check some options */
+
+  if(get_config_bool(lookup_config(config_tree, "IndirectData"), &choice))
+    if(choice)
+      myself->options |= OPTION_INDIRECT;
+
+  if(get_config_bool(lookup_config(config_tree, "TCPOnly"), &choice))
+    if(choice)
+      myself->options |= OPTION_TCPONLY;
+
+  if(get_config_bool(lookup_config(myself->connection->config_tree, "IndirectData"), &choice))
+    if(choice)
+      myself->options |= OPTION_INDIRECT;
+
+  if(get_config_bool(lookup_config(myself->connection->config_tree, "TCPOnly"), &choice))
+    if(choice)
+      myself->options |= OPTION_TCPONLY;
+
+  if(myself->options & OPTION_TCPONLY)
+    myself->options |= OPTION_INDIRECT;
+
+  if(get_config_string(lookup_config(config_tree, "Mode"), &mode))
+    {
+      if(!strcasecmp(mode, "router"))
+        routing_mode = RMODE_ROUTER;
+      else if (!strcasecmp(mode, "switch"))
+        routing_mode = RMODE_SWITCH;
+      else if (!strcasecmp(mode, "hub"))
+        routing_mode = RMODE_HUB;
+      else
+        {
+          syslog(LOG_ERR, _("Invalid routing mode!"));
+          return -1;
+        }
+      free(mode);
+    }
+  else
+    routing_mode = RMODE_ROUTER;
+
+  if(get_config_int(lookup_config(myself->connection->config_tree, "MaxTimeout"), &maxtimeout))
+    {
+      if(maxtimeout <= 0)
+        {
+          syslog(LOG_ERR, _("Bogus maximum timeout!"));
+          return -1;
+        }
+    }
+  else
+    maxtimeout = 900;
+
+  if(get_config_string(lookup_config(config_tree, "AddressFamily"), &afname))
+    {
+      if(!strcasecmp(afname, "IPv4"))
+        addressfamily = AF_INET;
+      else if (!strcasecmp(afname, "IPv6"))
+        addressfamily = AF_INET6;
+      else if (!strcasecmp(afname, "any"))
+        addressfamily = AF_UNSPEC;
+      else
+        {
+          syslog(LOG_ERR, _("Invalid address family!"));
+          return -1;
+        }
+      free(afname);
+    }
+  else
+    addressfamily = AF_INET;
+
+  get_config_bool(lookup_config(config_tree, "Hostnames"), &hostnames);
+cp
+  /* Generate packet encryption key */
+
+  if(get_config_string(lookup_config(myself->connection->config_tree, "Cipher"), &cipher))
+    {
+      if(!strcasecmp(cipher, "none"))
+        {
+          myself->cipher = NULL;
+        }
+      else
+        {
+          if(!(myself->cipher = EVP_get_cipherbyname(cipher)))
+            {
+              syslog(LOG_ERR, _("Unrecognized cipher type!"));
+              return -1;
+            }
+        }
+    }
+  else
+    myself->cipher = EVP_bf_cbc();
+
+  if(myself->cipher)
+    myself->keylength = myself->cipher->key_len + myself->cipher->iv_len;
+  else
+    myself->keylength = 1;
+
+  myself->key = (char *)xmalloc(myself->keylength);
+  RAND_pseudo_bytes(myself->key, myself->keylength);
+
+  if(!get_config_int(lookup_config(config_tree, "KeyExpire"), &keylifetime))
+    keylifetime = 3600;
+
+  keyexpires = time(NULL) + keylifetime;
+
+  /* Check if we want to use message authentication codes... */
+
+  if(get_config_string(lookup_config(myself->connection->config_tree, "Digest"), &digest))
+    {
+      if(!strcasecmp(digest, "none"))
+        {
+          myself->digest = NULL;
+        }
+      else
+        {
+          if(!(myself->digest = EVP_get_digestbyname(digest)))
+            {
+              syslog(LOG_ERR, _("Unrecognized digest type!"));
+              return -1;
+            }
+        }
+    }
+  else
+    myself->digest = EVP_sha1();
+
+  if(get_config_int(lookup_config(myself->connection->config_tree, "MACLength"), &myself->maclength))
+    {
+      if(myself->digest)
+        {
+          if(myself->maclength > myself->digest->md_size)
+            {
+              syslog(LOG_ERR, _("MAC length exceeds size of digest!"));
+              return -1;
+            }
+          else if (myself->maclength < 0)
+            {
+              syslog(LOG_ERR, _("Bogus MAC length!"));
+              return -1;
+            }
+        }
+    }
+  else
+    myself->maclength = 4;
+
+  /* Compression */
+
+  if(get_config_int(lookup_config(myself->connection->config_tree, "Compression"), &myself->compression))
+    {
+      if(myself->compression < 0 || myself->compression > 9)
+        {
+          syslog(LOG_ERR, _("Bogus compression level!"));
+          return -1;
+        }
+    }
+  else
+    myself->compression = 0;
+cp
+  /* Done */
+
+  myself->nexthop = myself;
+  myself->via = myself;
+  myself->status.active = 1;
+  node_add(myself);
+
+  graph();
+
+cp
+  /* Open sockets */
+  
+  hint.ai_family = (addressfamily == AF_UNSPEC)?AF_INET6:addressfamily;
+  hint.ai_socktype = SOCK_STREAM;
+  hint.ai_protocol = IPPROTO_TCP;
+  hint.ai_flags = AI_PASSIVE;
+
+  if(getaddrinfo(NULL, myport, &hint, &ai) || !ai)
+    {
+      syslog(LOG_ERR, _("System call `%s' failed: %s"), "getaddrinfo", strerror(errno));
+      return -1;
+    }
+
+  if((tcp_socket = setup_listen_socket((sockaddr_t *)ai->ai_addr)) < 0)
+    {
+      syslog(LOG_ERR, _("Unable to set up a listening TCP socket!"));
+      return -1;
+    }
+
+  if((udp_socket = setup_vpn_in_socket((sockaddr_t *)ai->ai_addr)) < 0)
+    {
+      syslog(LOG_ERR, _("Unable to set up a listening UDP socket!"));
+      return -1;
+    }
+
+  freeaddrinfo(ai);
+
+  syslog(LOG_NOTICE, _("Ready: listening on port %s"), myport);
+cp
+  return 0;
+}
+
+/*
+  setup all initial network connections
+*/
+int setup_network_connections(void)
+{
+cp
+  init_connections();
+  init_subnets();
+  init_nodes();
+  init_edges();
+  init_events();
+
+  if(get_config_int(lookup_config(config_tree, "PingTimeout"), &pingtimeout))
+    {
+      if(pingtimeout < 1)
+        {
+          pingtimeout = 86400;
+        }
+    }
+  else
+    pingtimeout = 60;
+
+  if(setup_device() < 0)
+    return -1;
+
+  /* Run tinc-up script to further initialize the tap interface */
+  execute_script("tinc-up");
+
+  if(setup_myself() < 0)
+    return -1;
+
+  try_outgoing_connections();
+cp
+  return 0;
+}
+
+/*
+  close all open network connections
+*/
+void close_network_connections(void)
+{
+  avl_node_t *node, *next;
+  connection_t *c;
+cp
+  for(node = connection_tree->head; node; node = next)
+    {
+      next = node->next;
+      c = (connection_t *)node->data;
+      if(c->outgoing)
+        free(c->outgoing->name), free(c->outgoing);
+      terminate_connection(c, 0);
+    }
+
+  if(myself && myself->connection)
+    terminate_connection(myself->connection, 0);
+
+  close(udp_socket);
+  close(tcp_socket);
+
+  exit_events();
+  exit_edges();
+  exit_subnets();
+  exit_nodes();
+  exit_connections();
+
+  execute_script("tinc-down");
+
+  close_device();
+cp
+  return;
+}
diff --git a/src/net_socket.c b/src/net_socket.c
new file mode 100644 (file)
index 0000000..93314fb
--- /dev/null
@@ -0,0 +1,456 @@
+/*
+    net_socket.c -- Handle various kinds of sockets.
+    Copyright (C) 1998-2002 Ivo Timmermans <itimmermans@bigfoot.com>,
+                  2000-2002 Guus Sliepen <guus@sliepen.warande.net>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+    $Id: net_socket.c,v 1.1.2.1 2002/02/18 16:25:16 guus Exp $
+*/
+
+#include "config.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#ifdef HAVE_LINUX
+ #include <netinet/ip.h>
+ #include <netinet/tcp.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+/* SunOS really wants sys/socket.h BEFORE net/if.h,
+   and FreeBSD wants these lines below the rest. */
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#include <utils.h>
+#include <xalloc.h>
+#include <avl_tree.h>
+#include <list.h>
+
+#include "conf.h"
+#include "connection.h"
+#include "meta.h"
+#include "net.h"
+#include "netutl.h"
+#include "process.h"
+#include "protocol.h"
+#include "subnet.h"
+#include "graph.h"
+#include "process.h"
+#include "route.h"
+#include "device.h"
+#include "event.h"
+
+#include "system.h"
+
+int addressfamily = AF_INET;
+int maxtimeout = 900;
+int seconds_till_retry = 5;
+
+int tcp_socket = -1;
+int udp_socket = -1;
+/* Setup sockets */
+
+int setup_listen_socket(sockaddr_t *sa)
+{
+  int nfd, flags;
+  char *addrstr;
+  int option;
+#ifdef HAVE_LINUX
+  char *interface;
+#endif
+cp
+  if((nfd = socket(sa->sa.sa_family, SOCK_STREAM, IPPROTO_TCP)) < 0)
+    {
+      syslog(LOG_ERR, _("Creating metasocket failed: %s"), strerror(errno));
+      return -1;
+    }
+
+  flags = fcntl(nfd, F_GETFL);
+  if(fcntl(nfd, F_SETFL, flags | O_NONBLOCK) < 0)
+    {
+      close(nfd);
+      syslog(LOG_ERR, _("System call `%s' failed: %s"), "fcntl", strerror(errno));
+      return -1;
+    }
+
+  /* Optimize TCP settings */
+
+  option = 1;
+  setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option));
+#ifdef HAVE_LINUX
+  setsockopt(nfd, SOL_TCP, TCP_NODELAY, &option, sizeof(option));
+
+  option = IPTOS_LOWDELAY;
+  setsockopt(nfd, SOL_IP, IP_TOS, &option, sizeof(option));
+
+  if(get_config_string(lookup_config(config_tree, "BindToInterface"), &interface))
+    if(setsockopt(nfd, SOL_SOCKET, SO_BINDTODEVICE, interface, strlen(interface)))
+      {
+        close(nfd);
+        syslog(LOG_ERR, _("Can't bind to interface %s: %s"), interface, strerror(errno));
+        return -1;
+      }
+#endif
+
+  if(bind(nfd, &sa->sa, sizeof(*sa)))
+    {
+      close(nfd);
+      addrstr = sockaddr2hostname(sa);
+      syslog(LOG_ERR, _("Can't bind to %s/tcp: %s"), addrstr, strerror(errno));
+      free(addrstr);
+      return -1;
+    }
+
+  if(listen(nfd, 3))
+    {
+      close(nfd);
+      syslog(LOG_ERR, _("System call `%s' failed: %s"), "listen", strerror(errno));
+      return -1;
+    }
+cp
+  return nfd;
+}
+
+int setup_vpn_in_socket(sockaddr_t *sa)
+{
+  int nfd, flags;
+  char *addrstr;
+  int option;
+#ifdef HAVE_LINUX
+  char *interface;
+#endif
+cp
+  if((nfd = socket(sa->sa.sa_family, SOCK_DGRAM, IPPROTO_UDP)) < 0)
+    {
+      syslog(LOG_ERR, _("Creating UDP socket failed: %s"), strerror(errno));
+      return -1;
+    }
+
+  flags = fcntl(nfd, F_GETFL);
+  if(fcntl(nfd, F_SETFL, flags | O_NONBLOCK) < 0)
+    {
+      close(nfd);
+      syslog(LOG_ERR, _("System call `%s' failed: %s"), "fcntl", strerror(errno));
+      return -1;
+    }
+
+  option = 1;
+  setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option));
+#ifdef HAVE_LINUX
+  if(get_config_string(lookup_config(config_tree, "BindToInterface"), &interface))
+    if(setsockopt(nfd, SOL_SOCKET, SO_BINDTODEVICE, interface, strlen(interface)))
+      {
+        close(nfd);
+        syslog(LOG_ERR, _("Can't bind to interface %s: %s"), interface, strerror(errno));
+        return -1;
+      }
+#endif
+
+  if(bind(nfd, &sa->sa, sizeof(*sa)))
+    {
+      close(nfd);
+      addrstr = sockaddr2hostname(sa);
+      syslog(LOG_ERR, _("Can't bind to %s/udp: %s"), addrstr, strerror(errno));
+      free(addrstr);
+      return -1;
+    }
+cp
+  return nfd;
+}
+
+void retry_outgoing(outgoing_t *outgoing)
+{
+  event_t *event;
+cp
+  outgoing->timeout += 5;
+  if(outgoing->timeout > maxtimeout)
+    outgoing->timeout = maxtimeout;
+
+  event = new_event();
+  event->handler = (event_handler_t)setup_outgoing_connection;
+  event->time = time(NULL) + outgoing->timeout;
+  event->data = outgoing;
+  event_add(event);
+
+  if(debug_lvl >= DEBUG_CONNECTIONS)
+    syslog(LOG_NOTICE, _("Trying to re-establish outgoing connection in %d seconds"), outgoing->timeout);
+cp
+}
+
+int setup_outgoing_socket(connection_t *c)
+{
+  int option;
+cp
+  if(debug_lvl >= DEBUG_CONNECTIONS)
+    syslog(LOG_INFO, _("Trying to connect to %s (%s)"), c->name, c->hostname);
+
+  c->socket = socket(c->address.sa.sa_family, SOCK_STREAM, IPPROTO_TCP);
+
+  if(c->socket == -1)
+    {
+      syslog(LOG_ERR, _("Creating socket for %s failed: %s"), c->hostname, strerror(errno));
+      return -1;
+    }
+
+  /* Optimize TCP settings */
+
+#ifdef HAVE_LINUX
+  option = 1;
+  setsockopt(c->socket, SOL_TCP, TCP_NODELAY, &option, sizeof(option));
+
+  option = IPTOS_LOWDELAY;
+  setsockopt(c->socket, SOL_IP, IP_TOS, &option, sizeof(option));
+#endif
+
+  /* Connect */
+
+  if(connect(c->socket, &c->address.sa, sizeof(c->address)) == -1)
+    {
+      close(c->socket);
+      syslog(LOG_ERR, _("%s: %s"), c->hostname, strerror(errno));
+      return -1;
+    }
+
+  if(debug_lvl >= DEBUG_CONNECTIONS)
+    syslog(LOG_INFO, _("Connected to %s (%s)"), c->name, c->hostname);
+cp
+  return 0;
+}
+
+
+void finish_connecting(connection_t *c)
+{
+cp
+  if(debug_lvl >= DEBUG_CONNECTIONS)
+    syslog(LOG_INFO, _("Connected to %s (%s)"), c->name, c->hostname);
+
+  c->last_ping_time = time(NULL);
+
+  send_id(c);
+cp
+}
+
+void do_outgoing_connection(connection_t *c)
+{
+  char *address, *port;
+  int option, result, flags;
+cp
+begin:
+  if(!c->outgoing->ai)
+    {
+      if(!c->outgoing->cfg)
+        {
+          if(debug_lvl >= DEBUG_CONNECTIONS)
+            syslog(LOG_ERR, _("Could not set up a meta connection to %s"), c->name);
+          c->status.remove = 1;
+         do_prune = 1;
+         retry_outgoing(c->outgoing);
+         return;
+        }
+
+      get_config_string(c->outgoing->cfg, &address);
+
+      if(!get_config_string(lookup_config(c->config_tree, "Port"), &port))
+       asprintf(&port, "655");
+
+      c->outgoing->ai = str2addrinfo(address, port, SOCK_STREAM);
+      free(address);
+      free(port);
+
+      c->outgoing->aip = c->outgoing->ai;
+      c->outgoing->cfg = lookup_config_next(c->config_tree, c->outgoing->cfg);
+    }
+
+  if(!c->outgoing->aip)
+    {
+      freeaddrinfo(c->outgoing->ai);
+      c->outgoing->ai = NULL;
+      goto begin;
+    }
+
+  memcpy(&c->address, c->outgoing->aip->ai_addr, c->outgoing->aip->ai_addrlen);
+  c->outgoing->aip = c->outgoing->aip->ai_next;
+
+  if(c->hostname)
+    free(c->hostname);
+
+  c->hostname = sockaddr2hostname(&c->address);
+
+  if(debug_lvl >= DEBUG_CONNECTIONS)
+    syslog(LOG_INFO, _("Trying to connect to %s (%s)"), c->name, c->hostname);
+
+  c->socket = socket(c->address.sa.sa_family, SOCK_STREAM, IPPROTO_TCP);
+
+  if(c->socket == -1)
+    {
+      if(debug_lvl >= DEBUG_CONNECTIONS)
+        syslog(LOG_ERR, _("Creating socket for %s failed: %s"), c->hostname, strerror(errno));
+
+      goto begin;
+    }
+
+  /* Optimize TCP settings */
+
+#ifdef HAVE_LINUX
+  option = 1;
+  setsockopt(c->socket, SOL_TCP, TCP_NODELAY, &option, sizeof(option));
+
+  option = IPTOS_LOWDELAY;
+  setsockopt(c->socket, SOL_IP, IP_TOS, &option, sizeof(option));
+#endif
+
+  /* Non-blocking */
+
+  flags = fcntl(c->socket, F_GETFL);
+
+  if(fcntl(c->socket, F_SETFL, flags | O_NONBLOCK) < 0)
+    {
+      syslog(LOG_ERR, _("fcntl for %s: %s"), c->hostname, strerror(errno));
+    }
+
+  /* Connect */
+
+  result = connect(c->socket, &c->address.sa, sizeof(c->address));
+
+  if(result == -1)
+    {
+      if(errno == EINPROGRESS)
+        {
+          c->status.connecting = 1;
+         return;
+       }
+
+      close(c->socket);
+
+      if(debug_lvl >= DEBUG_CONNECTIONS)
+        syslog(LOG_ERR, _("%s: %s"), c->hostname, strerror(errno));
+
+      goto begin;
+    }
+
+  finish_connecting(c);
+  return;
+cp
+}
+
+void setup_outgoing_connection(outgoing_t *outgoing)
+{
+  connection_t *c;
+  node_t *n;
+cp
+  n = lookup_node(outgoing->name);
+  
+  if(n)
+    if(n->connection)
+      {
+        if(debug_lvl >= DEBUG_CONNECTIONS)       
+          syslog(LOG_INFO, _("Already connected to %s"), outgoing->name);
+        n->connection->outgoing = outgoing;
+        return;
+      }
+
+  c = new_connection();
+  c->name = xstrdup(outgoing->name);
+
+  init_configuration(&c->config_tree);
+  read_connection_config(c);
+  
+  outgoing->cfg = lookup_config(c->config_tree, "Address");
+  
+  if(!outgoing->cfg)
+    {
+      syslog(LOG_ERR, _("No address specified for %s"), c->name);
+      free_connection(c);
+      free(outgoing->name);
+      free(outgoing);
+      return;
+    }
+  
+  c->outgoing = outgoing;
+  c->last_ping_time = time(NULL);
+
+  connection_add(c);
+
+  do_outgoing_connection(c);
+}
+
+/*
+  accept a new tcp connect and create a
+  new connection
+*/
+int handle_new_meta_connection()
+{
+  connection_t *c;
+  sockaddr_t sa;
+  int fd, len = sizeof(sa);
+cp
+  if((fd = accept(tcp_socket, &sa.sa, &len)) < 0)
+    {
+      syslog(LOG_ERR, _("Accepting a new connection failed: %s"), strerror(errno));
+      return -1;
+    }
+
+  c = new_connection();
+
+  c->address = sa;
+  c->hostname = sockaddr2hostname(&sa);
+  c->socket = fd;
+  c->last_ping_time = time(NULL);
+
+  if(debug_lvl >= DEBUG_CONNECTIONS)
+    syslog(LOG_NOTICE, _("Connection from %s"), c->hostname);
+
+  connection_add(c);
+
+  c->allow_request = ID;
+  send_id(c);
+cp
+  return 0;
+}
+
+void try_outgoing_connections(void)
+{
+  static config_t *cfg = NULL;
+  char *name;
+  outgoing_t *outgoing;
+cp
+  for(cfg = lookup_config(config_tree, "ConnectTo"); cfg; cfg = lookup_config_next(config_tree, cfg))
+    {
+      get_config_string(cfg, &name);
+
+      if(check_id(name))
+        {
+          syslog(LOG_ERR, _("Invalid name for outgoing connection in %s line %d"), cfg->file, cfg->line);
+          free(name);
+          continue;
+        }
+
+      outgoing = xmalloc_and_zero(sizeof(*outgoing));
+      outgoing->name = name;
+      setup_outgoing_connection(outgoing);
+    }
+}
index ed8cb4e538759c39d3980cd385d5888a4a992eda..a8c01f5330c45e460c62a47f5acb0635c3ad6ea3 100644 (file)
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-    $Id: device.c,v 1.1.2.1 2002/02/12 14:40:12 guus Exp $
+    $Id: device.c,v 1.1.2.2 2002/02/18 16:25:19 guus Exp $
 */
 
 #include "config.h"
 
 #include <stdio.h>
+#include <errno.h>
 #include <sys/types.h>
 #include <sys/uio.h>
 #include <sys/stat.h>
@@ -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;
     }
 
index 14ed5cef0e3db05aecc79fa730fbbdaad4d91402..2ad30fc6b057458b6a5ea5fd64975ec047a09fc2 100644 (file)
@@ -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 <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <signal.h>
 #include <sys/socket.h>
 #include <syslog.h>
 #include <arpa/inet.h>
 
 #include "system.h"
 
-char *hostlookup(unsigned long addr)
+int hostnames = 0;
+
+/*
+  Turn a string into a struct addrinfo.
+  Return NULL on failure.
+*/
+struct addrinfo *str2addrinfo(char *address, char *service, int socktype)
 {
-  char *name;
-  struct hostent *host = NULL;
-  struct in_addr in;
-  int lookup_hostname = 0;
+  struct addrinfo hint, *ai;
+  int err;
 cp
-  in.s_addr = addr;
-
-  get_config_bool(lookup_config(config_tree, "Hostnames"), &lookup_hostname);
+  memset(&hint, 0, sizeof(hint));
 
-  if(lookup_hostname)
-    host = gethostbyaddr((char *)&in, sizeof(in), AF_INET);
+  hint.ai_family = addressfamily;
+  hint.ai_socktype = socktype;
 
-  if(!lookup_hostname || !host)
+  if((err = getaddrinfo(address, service, &hint, &ai)))
     {
-      asprintf(&name, "%s", inet_ntoa(in));
+      if(debug_lvl >= DEBUG_ERROR)
+        syslog(LOG_WARNING, _("Error looking up %s port %s: %s\n"), address, service, gai_strerror(err));
+      cp_trace();
+      return NULL;
     }
-  else
+
+cp
+  return ai;
+}
+
+sockaddr_t str2sockaddr(char *address, char *port)
+{
+  struct addrinfo hint, *ai;
+  sockaddr_t result;
+  int err;
+cp
+  memset(&hint, 0, sizeof(hint));
+
+  hint.ai_family = AF_UNSPEC;
+  hint.ai_flags = AI_NUMERICHOST;
+  hint.ai_socktype = SOCK_STREAM;
+
+  if((err = getaddrinfo(address, port, &hint, &ai) || !ai))
     {
-      asprintf(&name, "%s", host->h_name);
+      syslog(LOG_ERR, _("Error looking up %s port %s: %s\n"), address, port, gai_strerror(err));
+      cp_trace();
+      raise(SIGFPE);
+      exit(0);
     }
+
+  result = *(sockaddr_t *)ai->ai_addr;
+  freeaddrinfo(ai);
 cp
-  return name;
+  return result;
 }
 
-/*
-  Turn a string into an IP address
-  return NULL on failure
-  Should support IPv6 and other stuff in the future.
-*/
-ipv4_t str2address(char *str)
+void sockaddr2str(sockaddr_t *sa, char **addrstr, char **portstr)
 {
-  ipv4_t address;
-  struct hostent *h;
+  char address[NI_MAXHOST];
+  char port[NI_MAXSERV];
+  int err;
 cp
-  if(!(h = gethostbyname(str)))
+  if((err = getnameinfo((struct sockaddr *)sa, sizeof(sockaddr_t), address, sizeof(address), port, sizeof(port), NI_NUMERICHOST|NI_NUMERICSERV)))
     {
-      if(debug_lvl >= DEBUG_ERROR)
-        syslog(LOG_WARNING, _("Error looking up `%s': %s\n"), str, strerror(errno));
-        
-      return 0;
+      syslog(LOG_ERR, _("Error while translating addresses: %s"), gai_strerror(err));
+      cp_trace();
+      raise(SIGFPE);
+      exit(0);
     }
 
-  address = ntohl(*((ipv4_t*)(h->h_addr_list[0])));
+  *addrstr = xstrdup(address);
+  *portstr = xstrdup(port);
 cp
-  return address;
 }
 
-char *address2str(ipv4_t address)
+char *sockaddr2hostname(sockaddr_t *sa)
 {
   char *str;
+  char address[NI_MAXHOST] = "unknown";
+  char port[NI_MAXSERV] = "unknown";
+  int err;
 cp
-  asprintf(&str, "%hu.%hu.%hu.%hu",
-          (unsigned short int)((address >> 24) & 255),
-          (unsigned short int)((address >> 16) & 255),
-          (unsigned short int)((address >> 8) & 255),
-          (unsigned short int)(address & 255));
+  if((err = getnameinfo((struct sockaddr *)sa, sizeof(sockaddr_t), address, sizeof(address), port, sizeof(port), hostnames?0:(NI_NUMERICHOST|NI_NUMERICSERV))))
+    {
+      syslog(LOG_ERR, _("Error while looking up hostname: %s"), gai_strerror(err));
+    }
+
+  asprintf(&str, _("%s port %s"), address, port);
 cp
   return str;
 }
+
+int sockaddrcmp(sockaddr_t *a, sockaddr_t *b)
+{
+  int result;
+cp
+  result = a->sa.sa_family - b->sa.sa_family;
+  
+  if(result)
+    return result;
+  
+  switch(a->sa.sa_family)
+    {
+      case AF_UNSPEC:
+        return 0;
+      case AF_INET:
+       return memcmp(&a->in, &b->in, sizeof(a->in));
+      case AF_INET6:
+       return memcmp(&a->in6, &b->in6, sizeof(a->in6));
+      default:
+        syslog(LOG_ERR, _("sockaddrcmp() was called with unknown address family %d, exitting!"), a->sa.sa_family);
+       cp_trace();
+        raise(SIGFPE);
+        exit(0);
+    }
+cp
+}
+
+/* Subnet mask handling */
+
+int maskcmp(char *a, char *b, int masklen, int len)
+{
+  int i, m, result;
+cp
+  for(m = masklen, i = 0; m > 8; m -= 8, i++)
+    if((result = a[i] - b[i]))
+      return result;
+
+  if(m)
+    return (a[i] & (0x100 - (m << 1))) - (b[i] & (0x100 - (m << 1)));
+
+  return 0;
+}
+
+void mask(char *a, int masklen, int len)
+{
+  int i;
+cp
+  i = masklen / 8;
+  masklen %= 8;
+  
+  if(masklen)
+    a[i++] &= (0x100 - (masklen << 1));
+  
+  for(; i < len; i++)
+    a[i] = 0;
+}
+
+void maskcpy(char *a, char *b, int masklen, int len)
+{
+  int i, m;
+cp
+  for(m = masklen, i = 0; m > 8; m -= 8, i++)
+    a[i] = b[i];
+
+  if(m)
+    {
+      a[i] = b[i] & (0x100 - (m << 1));
+      i++;
+    }
+
+  for(; i < len; i++)
+    a[i] = 0;
+}
+
+int maskcheck(char *a, int masklen, int len)
+{
+  int i;
+cp
+  i = masklen / 8;
+  masklen %= 8;
+  
+  if(masklen)
+    if(a[i++] & ~(0x100 - (masklen << 1)))
+      return -1;
+  
+  for(; i < len; i++)
+    if(a[i] != 0)
+      return -1;
+
+  return 0;
+}
index 3d1584f6537de5b365f47af95193c12f8b3d25e2..6207fd188d4b279df1a2f36aca5f4a36a7a97f4a 100644 (file)
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-    $Id: netutl.h,v 1.2.4.9 2002/02/11 10:16:18 guus Exp $
+    $Id: netutl.h,v 1.2.4.10 2002/02/18 16:25:16 guus Exp $
 */
 
 #ifndef __TINC_NETUTL_H__
 #define __TINC_NETUTL_H__
 
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+
 #include "net.h"
 
+extern int hostnames;
+
 extern char *hostlookup(unsigned long);
-extern ipv4_t str2address(char*);
-extern char *address2str(ipv4_t);
+extern struct addrinfo *str2addrinfo(char *, char *, int);
+extern sockaddr_t str2sockaddr(char *, char *);
+extern void sockaddr2str(sockaddr_t *, char **, char **);
+extern char *sockaddr2hostname(sockaddr_t *);
+extern int sockaddrcmp(sockaddr_t *, sockaddr_t *);
+extern int maskcmp(char *, char *, int, int);
+extern void maskcpy(char *, char *, int, int);
+extern void mask(char *, int, int);
+extern int maskcheck(char *, int, int);
 
 #endif /* __TINC_NETUTL_H__ */
index 2abd7fbf133ae2acd782f11ce91f3a328e2196e0..6e3b0f9b4de07b93fdcb4d67542bac43d1a4f89a 100644 (file)
@@ -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 <avl_tree.h>
 #include "node.h"
+#include "netutl.h"
 #include "net.h"
 #include <utils.h>
 #include <xalloc.h>
@@ -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:"-");
     }
     
index b662ccd0ba7cb8ff0e001182e6dc741964ccc493..64938521def4e8081764404cc377a778a2a138a3 100644 (file)
@@ -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__ */
index a24d2d0d36bea6e41c690fed41b2a3cbb2a9c8ce..8468b1927b750c0c459b95f918adfb1241f1566b 100644 (file)
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-    $Id: device.c,v 1.1.2.4 2002/02/11 12:33:01 guus Exp $
+    $Id: device.c,v 1.1.2.5 2002/02/18 16:25:19 guus Exp $
 */
 
 #include "config.h"
 
 #include <stdio.h>
+#include <errno.h>
 #include <sys/types.h>
 #include <sys/uio.h>
 #include <sys/stat.h>
@@ -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;
     }
 
index 4455b65f63a57dfcfbfb4901a4dc18189165f5c5..5cc32c665488856ec4fa13005be05163fec50173 100644 (file)
@@ -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;
         }
     }
index 1fad4b78e510d36318667d1c37b53ce236e6d845..8541d3da743ce712cfefbc79e9f79b202847dd5a 100644 (file)
@@ -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 */
index 9c83199b8a250de4dccc826d8c1c4a91f6a523e7..0c5ca353ff53d5ab5450b60abbeffe78ca5776f3 100644 (file)
@@ -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"
 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);
index 0e16565bbde40a9f115385647dd6a57cbe2e1d05..1ac3e12ae2372bc9f06ab8e5d79d16ef0b5b0665 100644 (file)
@@ -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)
     {
index cf0bb5340cfc4ce96dd84811c981b3fff10cdcd8..758068d8d1c763e135bf6b300df5f1917d4cfcf9 100644 (file)
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-    $Id: device.c,v 1.1.2.6 2002/02/11 14:20:46 guus Exp $
+    $Id: device.c,v 1.1.2.7 2002/02/18 16:25:19 guus Exp $
 */
 
 
 #include "config.h"
 
 #include <stdio.h>
+#include <errno.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
@@ -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;
     }
 
index 6745e2f4766790f0be304aa3a017715952bab7ac..5fdc045ae453dfe1d2697246630a8dc620d76c65 100644 (file)
@@ -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"
 #include <netdb.h>
 #include <netinet/in.h>
 
+#include <utils.h>
+#include <xalloc.h>
+#include <avl_tree.h>
+
 #include "conf.h"
 #include "net.h"
 #include "node.h"
 #include "subnet.h"
-#include "system.h"
+#include "netutl.h"
 
-#include <utils.h>
-#include <xalloc.h>
-#include <avl_tree.h>
+#include "system.h"
 
 /* lists type of subnet */
 
@@ -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;
 }
index 9657ad9c424cdcca3c5247da6d525a29bb428730..04e5c286286c5250a3f703254d88a7f2abeb7df0 100644 (file)
@@ -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;