diff --git a/HACKING b/HACKING index 24b4d46..b0b9e67 100644 --- a/HACKING +++ b/HACKING @@ -186,11 +186,88 @@ up to date so contacting the host will be faster after an long idle time. MAN PAGES --------- -Look at a non-installed man page like this (linux): +Look at a non-installed man page like this (linux/UNIX): nroff -man edge.8 | less +PACKET FORMAT +------------- + +Version 1 + + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + 0 ! Version=1 ! Message Type ! TTL ! Origin ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + 4 ! ! + 8 ! Community Name ! +12 ! ! +16 ! ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +20 ! Source MAC Address : + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +24 : Source MAC Address ! Destination MAC Address : + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +28 : Destination MAC Address ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +32 ! Public Peer ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + : : + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +40 : : + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + : : + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +48 : ! Alignment ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! Private Peer : + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +56 : : + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + : : + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +64 : : + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + : ! Alignment ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +72 ! Packet Type ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! Seq Number ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +80 ! CRC32 ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + Payload + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + +Version = 1 +MessageType = 1 +TTL = 1 +Origin = 1 +Community = 16 +src MAC = 6 +dst MAC = 6 +Pub Peer = 19 (20) +Priv Peer = 19 (20) +Pkt Type = 1 (4) +Seq = 4 +CRC = 4 +====================== +Total = 79 (84) + +Sizes in parentheses indicate alignment adjusted sizes on i686. The intel +alignment is also shown in the diagram. Some platforms have different alignment +padding. + +The above packet format describes the header of IP packets carried between edge +nodes. Payload is an encoded ethernet frame appended to the packet header. The +ethernet payload is encrypted and compressed. + +When the payload is created it is first encrypted with twofish, then compressed +using lzo1x_compress. When the payload is decoded it is first decompressed using +lzo1x_decompress_safe then decrypted using twofish. + ------- -April 2008 - Richard Andrews +January 2009 - Richard Andrews diff --git a/INSTALL b/INSTALL index d6e7a7b..45221d4 100644 --- a/INSTALL +++ b/INSTALL @@ -43,8 +43,8 @@ line in it: To build an RPM the hard way follow these steps. -$ cp -a n2ndir n2n-1.2 -$ tar czf n2n-1.2.tar.gz n2n-1.2 -$ mv n2n-1.2.tar.gz /usr/src/redhat/SOURCES +$ cp -a n2ndir n2n-1.3 +$ tar czf n2n-1.3.tar.gz n2n-1.3 +$ mv n2n-1.3.tar.gz /usr/src/redhat/SOURCES $ cp n2ndir/n2n.spec /usr/src/redhat/SPECS $ rpmbuild -bb n2n.spec diff --git a/Makefile b/Makefile index d53272a..485adc3 100644 --- a/Makefile +++ b/Makefile @@ -1,11 +1,18 @@ -N2N_VERSION="1.2.2" - +N2N_VERSION="1.3.2" ######## CC=gcc -CFLAGS+=-g -Wall -Wshadow -Wpointer-arith -Wmissing-declarations -Wnested-externs #-static +DEBUG?=-g +WARN?=-Wall -Wshadow -Wpointer-arith -Wmissing-declarations -Wnested-externs + +#Ultrasparc64 users experiencing SIGBUS should try the following gcc options +#(thanks to Robert Gibbon) +PLATOPTS_SPARC64=-mcpu=ultrasparc -pipe -fomit-frame-pointer -ffast-math -finline-functions -fweb -frename-registers -mapp-regs + + +CFLAGS+=$(DEBUG) $(WARN) $(OPTIONS) $(PLATOPTS) INSTALL=install MKDIR=mkdir -p @@ -48,9 +55,9 @@ $(N2N_LIB): $(N2N_OBJS) # $(RANLIB) $@ version.c: - echo $(N2N_VERSION) | sed -e 's/.*/char * version = "&";/' > version.c - uname -p | sed -e 's/.*/char * osName = "&";/' >> version.c - date +"%D %r" | sed -e 's/.*/char * buildDate = "&";/' >> version.c + @echo $(N2N_VERSION) | sed -e 's/.*/const char * version = "&";/' > version.c + @uname -p | sed -e 's/.*/const char * osName = "&";/' >> version.c + @date +"%D %r" | sed -e 's/.*/const char * buildDate = "&";/' >> version.c clean: rm -rf $(N2N_OBJS) $(N2N_LIB) $(APPS) $(DOCS) *.dSYM *~ version.c @@ -62,3 +69,8 @@ install: edge supernode edge.8.gz supernode.1.gz $(INSTALL_PROG) edge $(SBINDIR)/ $(INSTALL_DOC) edge.8.gz $(MAN8DIR)/ $(INSTALL_DOC) supernode.1.gz $(MAN1DIR)/ + +# Courtesy of Ole Tange + +deb: + dpkg-buildpackage \ No newline at end of file diff --git a/debian/README.Debian b/debian/README.Debian deleted file mode 100644 index 3c58a22..0000000 --- a/debian/README.Debian +++ /dev/null @@ -1,34 +0,0 @@ -n2n for Debian --------------- - -This package depends on the kernel having the TUN/TAP driver configured in using -CONFIG_TUN=yes. - - -Quickstart ----------- - - * Decide where to place your supernode. Suppose you put it on host a.b.c.d -at port xyw. - * Decide what encryption password you want to use to secure your data. -Suppose you use the password encryptme - * Decide the network name you want to use. Suppose you call it mynetwork. -Note that you can use your supernode/edge nodes to handle multiple networks, -not just one. - * Decide what IP address you plan to use on your edge nodes. Suppose you -use IP address 10.1.2.0/24 - * Start your applications: - - o #supernode > supernode -l xyw - o #edge node1> edge -a 10.1.2.1 -c mynetwork -k encryptme -l a.b.c.d:xyw - o #edge node2> edge -a 10.1.2.2 -c mynetwork -k encryptme -l a.b.c.d:xyw - - Now test your n2n network: - - o #edge node1> ping 10.1.2.2 - o #edge node2> ping 10.1.2.1 - -For more info check http://www.ntop.org/n2n - - - -- cristian paul peñaranda rojas Sat, 29 Nov 2008 00:31:58 -0500 diff --git a/debian/changelog b/debian/changelog deleted file mode 100644 index a5da4cf..0000000 --- a/debian/changelog +++ /dev/null @@ -1,6 +0,0 @@ -n2n (1.2.2~svn3653) unstable; urgency=low - - * Initial release (closes: Bug#507750) - - -- cristian paul peñaranda rojas Sat, 29 Nov 2008 00:31:58 -0500 - diff --git a/debian/compat b/debian/compat deleted file mode 100644 index 7ed6ff8..0000000 --- a/debian/compat +++ /dev/null @@ -1 +0,0 @@ -5 diff --git a/debian/control b/debian/control deleted file mode 100644 index e025500..0000000 --- a/debian/control +++ /dev/null @@ -1,14 +0,0 @@ -Source: n2n -Section: net -Priority: extra -Maintainer: cristian paul peñaranda rojas -Build-Depends: debhelper (>= 5), libc6-dev (>= 2.0), quilt -Standards-Version: 3.8.0 - -Package: n2n -Architecture: any -Depends: ${shlibs:Depends} -Description: Peer-to-Peer VPN network daemon - n2n is an open source VPN application which utilizes - a Peer-to-peer architecture for network membership - and routing. diff --git a/debian/copyright b/debian/copyright deleted file mode 100644 index 6e4cae6..0000000 --- a/debian/copyright +++ /dev/null @@ -1,110 +0,0 @@ -This package was debianized by cristian paul peñaranda rojas on -and is licensed under the GNU General Public License (GPL) version 3. -A copy of the GNU GPL version 2 is in `/usr/share/common-licenses/GPL-3'. - -Sat, 29 Nov 2008 00:31:58 -0500. - -The current Debian maintainer is cristian paul peñaranda rojas - -It was downloaded from https://svn.ntop.org/svn/ntop/trunk/n2n - -Upstream Author: Luca Deri deri@ntop.org - -Copyright: - - Copyright (C) 2008 Luca Deri - Copyright (C) 2008 Richard Andrews - - -License: - - 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 3 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 with - the Debian GNU/Linux distribution in file /usr/share/common-licenses/GPL; - if not, write to the Free Software Foundation, Inc., 51 Franklin St, - Fifth Floor, Boston, MA 02110-1301, USA. - - - On Debian systems, the complete text of the GNU General Public - License, version 3, can be found in /usr/share/common-licenses/GPL-3. - -The Files: - - twofish.c - twofish.h - - Copyright (C) 1997-2000 The Cryptix Foundation Limited. - Copyright (C) 2000 Farm9. - Copyright (C) 2001 Frank Knobbe. - All rights reserved. - -For Cryptix code: - Use, modification, copying and distribution of this software is subject - the terms and conditions of the Cryptix General Licence. - - Cryptix General License - -Copyright (c) 1995 -2005 The Cryptix Foundation Limited. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - 1. Redistributions of source code must retain the copyright notice, - this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - -THIS SOFTWARE IS PROVIDED BY THE CRYPTIX FOUNDATION LIMITED AND -CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE CRYPTIX FOUNDATION LIMITED OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -The Files: - - minilzo.c - minilzo.h - lzodefs.h - -Copyright (C) 1996 - 2005 Markus Franz Xaver Johannes Oberhumer - -These file are part of the LZO real-time data compression library. - - All Rights Reserved. - - The LZO library 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. - - The LZO library 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 the LZO library; see the file COPYING. - If not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - diff --git a/debian/dirs b/debian/dirs deleted file mode 100644 index ca882bb..0000000 --- a/debian/dirs +++ /dev/null @@ -1,2 +0,0 @@ -usr/bin -usr/sbin diff --git a/debian/docs b/debian/docs deleted file mode 100644 index e845566..0000000 --- a/debian/docs +++ /dev/null @@ -1 +0,0 @@ -README diff --git a/debian/patches/01-edge.8.diff b/debian/patches/01-edge.8.diff deleted file mode 100644 index 0194e87..0000000 --- a/debian/patches/01-edge.8.diff +++ /dev/null @@ -1,8 +0,0 @@ ---- a/edge.8.old 2008-12-02 20:33:54.000000000 -0500 -+++ b/edge.8 2008-12-02 20:34:13.000000000 -0500 -@@ -1,4 +1,4 @@ --.TH edge 1 "May 3, 2008" "revision 3472" "SUPERUSER COMMANDS" -+.TH edge 8 "May 3, 2008" "revision 3472" "SUPERUSER COMMANDS" - .SH NAME - edge \- n2n edge node daemon - .SH SYNOPSIS diff --git a/debian/patches/series b/debian/patches/series deleted file mode 100644 index a92f0fe..0000000 --- a/debian/patches/series +++ /dev/null @@ -1 +0,0 @@ -01-edge.8.diff diff --git a/debian/rules b/debian/rules deleted file mode 100755 index 5494adf..0000000 --- a/debian/rules +++ /dev/null @@ -1,79 +0,0 @@ -#!/usr/bin/make -f -# -*- makefile -*- -# Uncomment this to turn on verbose mode. -#export DH_VERBOSE=1 - - -include /usr/share/quilt/quilt.make - -CFLAGS = -Wall -g - -ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) - CFLAGS += -O0 -else - CFLAGS += -O2 -endif - -configure: configure-stamp -configure-stamp: - dh_testdir - # Add here commands to configure the package. - - touch configure-stamp - - -build: patch build-stamp - -build-stamp: configure-stamp - dh_testdir - - # Add here commands to compile the package. - $(MAKE) - #docbook-to-man debian/n2n.sgml > n2n.1 - - touch $@ - -clean: unpatch - dh_testdir - dh_testroot - rm -f build-stamp configure-stamp - - # Add here commands to clean up after the build process. - [ ! -f Makefile ] || $(MAKE) clean - - dh_clean - -install: build - dh_testdir - dh_testroot - dh_clean -k - dh_installdirs - - # Add here commands to install the package into debian/n2n. - $(MAKE) DESTDIR=$(CURDIR)/debian/n2n install - - -# Build architecture-independent files here. -binary-indep: build install -# We have nothing to do by default. - -# Build architecture-dependent files here. -binary-arch: build install - dh_testdir - dh_testroot - dh_installchangelogs - dh_installdocs - dh_installexamples - dh_installman supernode.1 edge.8 - dh_link - dh_strip - dh_compress - dh_fixperms - dh_installdeb - dh_shlibdeps - dh_gencontrol - dh_md5sums - dh_builddeb - -binary: binary-indep binary-arch -.PHONY: build clean binary-indep binary-arch binary install configure diff --git a/edge.8 b/edge.8 index a5f400c..37d6861 100644 --- a/edge.8 +++ b/edge.8 @@ -1,4 +1,4 @@ -.TH edge 1 "May 3, 2008" "revision 3472" "SUPERUSER COMMANDS" +.TH edge 1 "Jan 3, 2009" "revision 3679" "SUPERUSER COMMANDS" .SH NAME edge \- n2n edge node daemon .SH SYNOPSIS @@ -13,65 +13,104 @@ begin to find other nodes in the community. .PP .SH OPTIONS .TP -\-d +\-d sets the TAP device name as seen in ifconfig. .TP -\-a -sets the n2n LAN IP address being claimed. +\-a +sets the n2n virtual LAN IP address being claimed. This is a private IP +address. All IP addresses in an n2n community should belong to the same /24 +network (ie. only the last segment of the IP addresses varies). .TP -\-c -sets the n2n community name. +\-b +cause edge to perform hostname resolution for the supernode address each time +the supernode is periodically contacted. .TP -\-k -sets the twofish encryption key from ASCII text (see also N2N_KEY in ENVIRONMENT) +\-c +sets the n2n community name. All edges within the same community look to be on +the same LAN (layer 2 network segment). All edges communicating must use the +same key and community name. .TP -\-l -sets the n2n supernode IP address and port to register to +\-h +write usage to tty then exit. .TP -\-p -binds to the given UDP port +\-k +sets the twofish encryption key from ASCII text (see also N2N_KEY in +ENVIRONMENT). All edges communicating must use the same key and community name. .TP -\-u -causes the edge process to drop to the given user ID when privileges are no longer required +\-l : +sets the n2n supernode IP address and port to register to. .TP -\-g -causes the edge process to drop to the given group ID when privileges are no longer required +\-p +binds edge to the given UDP port. Useful for keeping the same external socket +across restarts of edge. +.TP +\-u +causes the edge process to drop to the given user ID when privileges are no +longer required. +.TP +\-g +causes the edge process to drop to the given group ID when privileges are no +longer required. .TP \-f -causes the edge process to fork and run as a daemon, closing stdin, stdout, stderr and becoming a process group leader +causes the edge process to fork and run as a daemon, closing stdin, stdout, +stderr and becoming a process group leader. .TP -\-m +\-m start the TAP interface with the given MAC address. This is highly recommended as it means the same address will be used if edge stops and restarts. If this is not done, the ARP caches of all peers will be wrong and packets will not flow to this edge until the next ARP refresh. .TP +\-M +set the MTU of the edge interface in bytes. MTU is the largest packet fragment +size allowed to be moved throught the interface. The default is 1400. +.TP +\-s +set the netmask of edge interface in IPv4 dotted decimal notation. The default +is 255.255.255.0 (ie. /24). +.TP \-t -use HTTP tunneling instead of the normal UDP mechanism (experimental) +use HTTP tunneling instead of the normal UDP mechanism (experimental). .TP \-r -all packet forwarding/routing through the n2n virtual LAN +enable packet forwarding/routing through the n2n virtual LAN. Without this +option, packets arriving over n2n which are not for the -a IP address are +dropped. .TP \-v -use verbose logging +use verbose logging. .SH ENVIRONMENT .TP .B N2N_KEY set the encryption key so it is not visible on the command line .SH EXAMPLES .TP -.B edge \-d n2n0 \-c mynetwork \-k encryptme \-u 99 \-g 99 \-m DE:AD:BE:EF:01:23 \-a 192.168.254.7 \-l 123.121.120.119:7654 +.B edge \-d n2n0 \-c mynetwork \-k encryptme \-u 99 \-g 99 \-m DE:AD:BE:EF:01:23 \-a 192.168.254.7 \-p 50001 \-l 123.121.120.119:7654 Start edge with TAP device n2n0 on community "mynetwork" with community -supernode at 123.121.120.119 UDP port 7654. Use "encryptme" as the shared -encryption key. Assign MAC address DE:AD:BE:EF:01:23 to the n2n interface and -drop to user=99 and group=99 after the TAP device is successfull configured. +supernode at 123.121.120.119 UDP port 7654 and bind the locally used UDP port to +50001. Use "encryptme" as the shared encryption key. Assign MAC address +DE:AD:BE:EF:01:23 to the n2n interface and drop to user=99 and group=99 after +the TAP device is successfull configured. .PP -Add the -f option to make it run as a daemon +Add the -f option to make edge run as a daemon. .PP +Somewhere else setup another edge with similar parameters, eg. + +.B edge \-d n2n0 \-c mynetwork \-k encryptme \-u 99 \-g 99 \-m DE:AD:BE:EF:01:21 \-a 192.168.254.5 \-p 50001 \-l 123.121.120.119:7654 +.PP +Now you can ping from 192.168.254.5 to 192.168.254.7. +.PP +The MAC address (-m ) and virtual IP address (-a ) must be different on all edges in the same community. + +.SH CONFIGURATION +All configuration for edge is from the command line and environment +variables. If you wish to reconfigure edge you should kill the process and +restart with the desired options. .SH EXIT STATUS -edge is a daemon and any exit is an error +edge is a daemon and any exit is an error. .SH AUTHOR Luca Deri ( deri (at) ntop.org ), Richard Andrews ( andrews (at) ntop.org ), Don Bindner .SH SEE ALSO -ifconfig(1) supernode(1) tunctl(1) +ifconfig(8) supernode(1) tunctl(8) diff --git a/edge.c b/edge.c index 2a67ef7..5f69c5a 100644 --- a/edge.c +++ b/edge.c @@ -1,5 +1,6 @@ /* * (C) 2007-09 - Luca Deri + * Richard Andrews * * 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 @@ -15,8 +16,9 @@ * along with this program; if not see see * * Code contributions courtesy of: - * Richard Andrews * Don Bindner + * Sylwester Sosnowski + * Wilfried "Wonka" Klaebe * */ @@ -49,7 +51,8 @@ struct n2n_edge int allow_routing /*= 0*/; int drop_ipv6_ndp /*= 0*/; char * encrypt_key /* = NULL*/; - TWOFISH * tf; + TWOFISH * enc_tf; + TWOFISH * dec_tf; struct peer_info * known_peers /* = NULL*/; struct peer_info * pending_peers /* = NULL*/; @@ -141,7 +144,7 @@ static char ** buildargv(char * const linebuffer) { char ** argv; char * buffer, * buff; - buffer = (char *)malloc(strlen(linebuffer)+2); + buffer = (char *)calloc(1, strlen(linebuffer)+2); if (!buffer) { traceEvent( TRACE_ERROR, "Unable to allocate memory"); return NULL; @@ -199,7 +202,8 @@ static int edge_init(n2n_edge_t * eee) { eee->allow_routing = 0; eee->drop_ipv6_ndp = 0; eee->encrypt_key = NULL; - eee->tf = NULL; + eee->enc_tf = NULL; + eee->dec_tf = NULL; eee->known_peers = NULL; eee->pending_peers = NULL; eee->last_register = 0; @@ -214,9 +218,10 @@ static int edge_init(n2n_edge_t * eee) { static int edge_init_twofish( n2n_edge_t * eee, u_int8_t *encrypt_pwd, u_int32_t encrypt_pwd_len ) { - eee->tf = TwoFishInit(encrypt_pwd, encrypt_pwd_len); + eee->enc_tf = TwoFishInit(encrypt_pwd, encrypt_pwd_len); + eee->dec_tf = TwoFishInit(encrypt_pwd, encrypt_pwd_len); - if ( eee->tf ) + if ( (eee->enc_tf) && (eee->dec_tf) ) { return 0; } @@ -229,7 +234,8 @@ static int edge_init_twofish( n2n_edge_t * eee, u_int8_t *encrypt_pwd, u_int32_t /* ************************************** */ static void edge_deinit(n2n_edge_t * eee) { - TwoFishDestroy(eee->tf); + TwoFishDestroy(eee->enc_tf); + TwoFishDestroy(eee->dec_tf); if ( eee->sinfo.sock >=0 ) { close( eee->sinfo.sock ); @@ -248,6 +254,7 @@ static void help() { "-a " "-c " "-k " + "-s " #ifndef WIN32 "[-u -g ]" "[-f]" @@ -255,7 +262,7 @@ static void help() { "[-m ]" "\n" "-l " - "[-p ] " + "[-p ] [-M ] " "[-t] [-r] [-v] [-b] [-h]\n\n"); #ifdef __linux__ @@ -265,6 +272,7 @@ static void help() { printf("-a | n2n IP address\n"); printf("-c | n2n community name\n"); printf("-k | Encryption key (ASCII) - also N2N_KEY=\n"); + printf("-s | Edge interface netmask in dotted decimal notation (255.255.255.0)\n"); printf("-l | Supernode IP:port\n"); printf("-b | Periodically resolve supernode IP\n"); printf(" | (when supernodes are running on dynamic IPs)\n"); @@ -276,6 +284,7 @@ static void help() { #endif printf("-m | Choose a MAC address for the TAP interface\n" " | eg. -m 01:02:03:04:05:06\n"); + printf("-M | Specify n2n MTU (default %d)\n", DEFAULT_MTU); printf("-t | Use http tunneling (experimental)\n"); printf("-r | Enable packet forwarding through n2n community\n"); printf("-v | Verbose\n"); @@ -288,7 +297,6 @@ static void help() { /* *********************************************** */ - static void send_register( n2n_edge_t * eee, const struct peer_addr *remote_peer, u_char is_ack) { @@ -303,9 +311,9 @@ static void send_register( n2n_edge_t * eee, memcpy(hdr.community_name, eee->community_name, COMMUNITY_LEN); marshall_n2n_packet_header( (u_int8_t *)pkt, &hdr ); - send_packet( &(eee->sinfo), pkt, &len, remote_peer, 1 ); + send_packet( &(eee->sinfo), pkt, &len, remote_peer, N2N_COMPRESSION_ENABLED ); - traceEvent(TRACE_INFO, "Sent %s message to %s:%d", + traceEvent(TRACE_INFO, "Sent %s message to %s:%hd", ((hdr.msg_type==MSG_TYPE_REGISTER)?"MSG_TYPE_REGISTER":"MSG_TYPE_REGISTER_ACK"), intoa(ntohl(remote_peer->addr_type.v4_addr), ip_buf, sizeof(ip_buf)), ntohs(remote_peer->port)); @@ -325,7 +333,7 @@ static void send_deregister(n2n_edge_t * eee, memcpy(hdr.community_name, eee->community_name, COMMUNITY_LEN); marshall_n2n_packet_header( (u_int8_t *)pkt, &hdr ); - send_packet( &(eee->sinfo), pkt, &len, remote_peer, 1); + send_packet( &(eee->sinfo), pkt, &len, remote_peer, N2N_COMPRESSION_ENABLED); } /* *********************************************** */ @@ -377,7 +385,7 @@ void try_send_register( n2n_edge_t * eee, traceEvent( TRACE_NORMAL, "Pending peers list size=%ld", peer_list_size( eee->pending_peers ) ); - traceEvent( TRACE_NORMAL, "Sending REGISTER request to %s:%d", + traceEvent( TRACE_NORMAL, "Sending REGISTER request to %s:%hd", intoa(ntohl(scan->public_ip.addr_type.v4_addr), ip_buf, sizeof(ip_buf)), ntohs(scan->public_ip.port)); @@ -396,7 +404,7 @@ void try_send_register( n2n_edge_t * eee, /* over-write supernode-based socket with direct socket. */ scan->public_ip = hdr->public_ip; - traceEvent( TRACE_NORMAL, "Sending additional REGISTER request to %s:%d", + traceEvent( TRACE_NORMAL, "Sending additional REGISTER request to %s:%hd", intoa(ntohl(scan->public_ip.addr_type.v4_addr), ip_buf, sizeof(ip_buf)), ntohs(scan->public_ip.port)); @@ -473,7 +481,7 @@ void set_peer_operational( n2n_edge_t * eee, const struct n2n_packet_header * hd scan->public_ip = hdr->public_ip; - traceEvent(TRACE_INFO, "=== new peer [mac=%s][socket=%s:%d]", + traceEvent(TRACE_INFO, "=== new peer [mac=%s][socket=%s:%hd]", macaddr_str(scan->mac_addr, mac_buf, sizeof(mac_buf)), intoa(ntohl(scan->public_ip.addr_type.v4_addr), ip_buf, sizeof(ip_buf)), ntohs(scan->public_ip.port)); @@ -501,7 +509,7 @@ void trace_registrations( struct peer_info * scan ) while ( scan ) { - traceEvent(TRACE_INFO, "=== peer [mac=%s][socket=%s:%d]", + traceEvent(TRACE_INFO, "=== peer [mac=%s][socket=%s:%hd]", macaddr_str(scan->mac_addr, mac_buf, sizeof(mac_buf)), intoa(ntohl(scan->public_ip.addr_type.v4_addr), ip_buf, sizeof(ip_buf)), ntohs(scan->public_ip.port)); @@ -563,7 +571,7 @@ static void update_peer_address(n2n_edge_t * eee, { if ( 0 == hdr->sent_by_supernode ) { - traceEvent( TRACE_NORMAL, "Peer changed public socket, Was %s:%d", + traceEvent( TRACE_NORMAL, "Peer changed public socket, Was %s:%hd", intoa(ntohl(hdr->public_ip.addr_type.v4_addr), ip_buf, sizeof(ip_buf)), ntohs(hdr->public_ip.port)); @@ -686,7 +694,7 @@ static int find_peer_destination(n2n_edge_t * eee, mac_address[3] & 0xFF, mac_address[4] & 0xFF, mac_address[5] & 0xFF); while(scan != NULL) { - traceEvent(TRACE_INFO, "Evaluating peer [MAC=%02X:%02X:%02X:%02X:%02X:%02X][ip=%s:%d]", + traceEvent(TRACE_INFO, "Evaluating peer [MAC=%02X:%02X:%02X:%02X:%02X:%02X][ip=%s:%hd]", scan->mac_addr[0] & 0xFF, scan->mac_addr[1] & 0xFF, scan->mac_addr[2] & 0xFF, scan->mac_addr[3] & 0xFF, scan->mac_addr[4] & 0xFF, scan->mac_addr[5] & 0xFF, intoa(ntohl(scan->public_ip.addr_type.v4_addr), ip_buf, sizeof(ip_buf)), @@ -707,7 +715,7 @@ static int find_peer_destination(n2n_edge_t * eee, memcpy(destination, &(eee->supernode), sizeof(struct sockaddr_in)); } - traceEvent(TRACE_INFO, "find_peer_address(%s) -> [socket=%s:%d]", + traceEvent(TRACE_INFO, "find_peer_address(%s) -> [socket=%s:%hd]", macaddr_str( (char *)mac_address, mac_buf, sizeof(mac_buf)), intoa(ntohl(destination->addr_type.v4_addr), ip_buf, sizeof(ip_buf)), ntohs(destination->port)); @@ -746,18 +754,17 @@ static void send_packet2net(n2n_edge_t * eee, /* Discard IP packets that are not originated by this hosts */ if(!(eee->allow_routing)) { if(ntohs(eh->ether_type) == 0x0800) { - /* This is an IP packet from the local source address - not forwarded. */ #define ETH_FRAMESIZE 14 #define IP4_SRCOFFSET 12 -#define IP4_ADDRSIZE 4 + u_int32_t *dst = (u_int32_t*)&decrypted_msg[ETH_FRAMESIZE + IP4_SRCOFFSET]; + /* Note: all elements of the_ip are in network order */ - if( 0 != memcmp( decrypted_msg + ETH_FRAMESIZE + IP4_SRCOFFSET, - &(eee->device.ip_addr), - IP4_ADDRSIZE ) ) { - /* This is a packet that needs to be routed */ - traceEvent(TRACE_INFO, "Discarding routed packet"); - return; + if( *dst != eee->device.ip_addr) { + /* This is a packet that needs to be routed */ + traceEvent(TRACE_INFO, "Discarding routed packet [%s]", + intoa(ntohl(*dst), ip_buf, sizeof(ip_buf))); + return; } else { /* This packet is originated by us */ /* traceEvent(TRACE_INFO, "Sending non-routed packet"); */ @@ -767,7 +774,7 @@ static void send_packet2net(n2n_edge_t * eee, /* Encrypt "decrypted_msg" into the second half of the n2n packet. */ len = TwoFishEncryptRaw((u_int8_t *)decrypted_msg, - (u_int8_t *)&packet[N2N_PKT_HDR_SIZE], len, eee->tf); + (u_int8_t *)&packet[N2N_PKT_HDR_SIZE], len, eee->enc_tf); /* Add the n2n header to the start of the n2n packet. */ fill_standard_header_fields( &(eee->sinfo), &hdr, (char*)(eee->device.mac_addr) ); @@ -781,7 +788,7 @@ static void send_packet2net(n2n_edge_t * eee, len += N2N_PKT_HDR_SIZE; if(find_peer_destination(eee, eh->ether_dhost, &destination)) - traceEvent(TRACE_INFO, "** Going direct [dst_mac=%s][dest=%s:%d]", + traceEvent(TRACE_INFO, "** Going direct [dst_mac=%s][dest=%s:%hd]", macaddr_str((char*)eh->ether_dhost, mac_buf, sizeof(mac_buf)), intoa(ntohl(destination.addr_type.v4_addr), ip_buf, sizeof(ip_buf)), ntohs(destination.port)); @@ -790,7 +797,8 @@ static void send_packet2net(n2n_edge_t * eee, macaddr_str((char*)eh->ether_shost, mac_buf, sizeof(mac_buf)), macaddr_str((char*)eh->ether_dhost, mac2_buf, sizeof(mac2_buf))); - data_sent_len = reliable_sendto( &(eee->sinfo), packet, &len, &destination, 1); + data_sent_len = reliable_sendto( &(eee->sinfo), packet, &len, &destination, + N2N_COMPRESSION_ENABLED); if(data_sent_len != len) traceEvent(TRACE_WARNING, "sendto() [sent=%d][attempted_to_send=%d] [%s]\n", @@ -850,6 +858,8 @@ static int check_received_packet(n2n_edge_t * eee, char *pkt, } else if(pkt_len > 32 /* IP + Ethernet */) { /* Check if this packet is for us or if it's routed */ struct ether_header *eh = (struct ether_header*)pkt; + + const struct in_addr bcast = { 0xffffffff }; if(ntohs(eh->ether_type) == 0x0800) { @@ -857,8 +867,14 @@ static int check_received_packet(n2n_edge_t * eee, char *pkt, struct ip *the_ip = (struct ip*)(pkt+sizeof(struct ether_header)); if((the_ip->ip_dst.s_addr != eee->device.ip_addr) - && ((the_ip->ip_dst.s_addr & eee->device.device_mask) != (eee->device.ip_addr & eee->device.device_mask))) /* Not a broadcast */ - { + && ((the_ip->ip_dst.s_addr & eee->device.device_mask) != (eee->device.ip_addr & eee->device.device_mask)) /* Not a broadcast */ + && ((the_ip->ip_dst.s_addr & 0xE0000000) != (0xE0000000 /* 224.0.0.0-239.255.255.255 */)) /* Not a multicast */ + && ((the_ip->ip_dst.s_addr) != (bcast.s_addr)) /* always broadcast (RFC919) */ + && (!(eee->allow_routing)) /* routing is enabled so let it in */ + ) + { + /* Dropping the packet */ + ipstr_t ip_buf; ipstr_t ip_buf2; @@ -866,7 +882,7 @@ static int check_received_packet(n2n_edge_t * eee, char *pkt, traceEvent(TRACE_INFO, "Discarding routed packet [rcvd=%s][expected=%s]", intoa(ntohl(the_ip->ip_dst.s_addr), ip_buf, sizeof(ip_buf)), intoa(ntohl(eee->device.ip_addr), ip_buf2, sizeof(ip_buf2))); - } else { + } else { /* This packet is for us */ /* traceEvent(TRACE_INFO, "Received non-routed packet"); */ @@ -927,7 +943,8 @@ void readFromIPSocket( n2n_edge_t * eee ) struct n2n_packet_header hdr_storage; len = receive_data( &(eee->sinfo), packet, sizeof(packet), &sender, - &discarded_pkt, (char*)(eee->device.mac_addr), 1, &hdr_storage); + &discarded_pkt, (char*)(eee->device.mac_addr), + N2N_COMPRESSION_ENABLED, &hdr_storage); if(len <= 0) return; @@ -944,7 +961,7 @@ void readFromIPSocket( n2n_edge_t * eee ) else { struct n2n_packet_header *hdr = &hdr_storage; - traceEvent(TRACE_INFO, "Received packet from %s:%d", + traceEvent(TRACE_INFO, "Received packet from %s:%hd", intoa(ntohl(sender.addr_type.v4_addr), ip_buf, sizeof(ip_buf)), ntohs(sender.port)); @@ -953,7 +970,7 @@ void readFromIPSocket( n2n_edge_t * eee ) hdr->sent_by_supernode ? "supernode" : "peer", macaddr_str(hdr->dst_mac, mac_buf, sizeof(mac_buf))); - if(hdr->version != N2N_VERSION) { + if(hdr->version != N2N_PKT_VERSION) { traceEvent(TRACE_WARNING, "Received packet with unknown protocol version (%d): discarded\n", hdr->version); @@ -978,7 +995,7 @@ void readFromIPSocket( n2n_edge_t * eee ) /* Decrypt message first */ len = TwoFishDecryptRaw((u_int8_t *)&packet[N2N_PKT_HDR_SIZE], - (u_int8_t *)decrypted_msg, len, eee->tf); + (u_int8_t *)decrypted_msg, len, eee->dec_tf); if(len > 0) { if(check_received_packet(eee, decrypted_msg, len) == 0) { @@ -998,13 +1015,13 @@ void readFromIPSocket( n2n_edge_t * eee ) traceEvent(TRACE_INFO, "### Tx L2 Msg -> tun"); } } else { - traceEvent(TRACE_WARNING, "Bad destination: message discarded"); + traceEvent(TRACE_WARNING, "Bad destination: message discarded"); } } /* else silently ignore empty packet. */ } else if(hdr->msg_type == MSG_TYPE_REGISTER) { - traceEvent(TRACE_INFO, "Received registration request from remote peer [ip=%s:%d]", + traceEvent(TRACE_INFO, "Received registration request from remote peer [ip=%s:%hd]", intoa(ntohl(hdr->public_ip.addr_type.v4_addr), ip_buf, sizeof(ip_buf)), ntohs(hdr->public_ip.port)); if ( 0 == memcmp(hdr->dst_mac, (eee->device.mac_addr), 6) ) @@ -1015,7 +1032,7 @@ void readFromIPSocket( n2n_edge_t * eee ) send_register(eee, &hdr->public_ip, 1); /* Send ACK back */ } else if(hdr->msg_type == MSG_TYPE_REGISTER_ACK) { - traceEvent(TRACE_NORMAL, "Received REGISTER_ACK from remote peer [ip=%s:%d]", + traceEvent(TRACE_NORMAL, "Received REGISTER_ACK from remote peer [ip=%s:%hd]", intoa(ntohl(hdr->public_ip.addr_type.v4_addr), ip_buf, sizeof(ip_buf)), ntohs(hdr->public_ip.port)); @@ -1116,7 +1133,7 @@ static void supernode2addr(n2n_edge_t * eee, char* addr) { eee->supernode.addr_type.v4_addr = inet_addr(supernode_host); } - traceEvent(TRACE_NORMAL, "Using supernode %s:%d", + traceEvent(TRACE_NORMAL, "Using supernode %s:%hd", intoa(ntohl(eee->supernode.addr_type.v4_addr), ip_buf, sizeof(ip_buf)), ntohs(eee->supernode.port)); } else @@ -1127,10 +1144,16 @@ static void supernode2addr(n2n_edge_t * eee, char* addr) { extern int useSyslog; +#define N2N_NETMASK_STR_SIZE 16 /* dotted decimal 12 numbers + 3 dots */ + + int main(int argc, char* argv[]) { int opt, local_port = 0 /* any port */; char *tuntap_dev_name = "edge0"; char *ip_addr = NULL; + char netmask[N2N_NETMASK_STR_SIZE]="255.255.255.0"; + int mtu = DEFAULT_MTU; + int got_s = 0; #ifndef WIN32 uid_t userid=0; /* root is the only guaranteed ID */ @@ -1142,7 +1165,7 @@ int main(int argc, char* argv[]) { time_t lastStatus=0; char * device_mac=NULL; - char * encrypt_key; + char * encrypt_key=NULL; int i, effectiveargc=0; char ** effectiveargv=NULL; @@ -1171,6 +1194,12 @@ int main(int argc, char* argv[]) { exit(1); } snprintf(linebuffer, MAX_CMDLINE_BUFFER_LENGTH, "%s",argv[0]); + +#ifdef WIN32 + for(i=0; i + * (C) 2007-09 - Luca Deri + * Richard Andrews * * 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 @@ -74,10 +75,13 @@ extern void peer_addr2sockaddr_in(const struct peer_addr *in, struct sockaddr_in /* ************************************** */ static -int marshall_peer_addr( u_int8_t * buf, const struct peer_addr * s ) +int marshall_peer_addr( u_int8_t * buf, size_t * offset, const struct peer_addr * s ) { - memcpy( buf, s, sizeof(struct peer_addr)); - buf += sizeof(struct peer_addr); + /* RA: I'm pretty sure that this is broken. There is no guarantee that the + * peer_addr structure is packed. This will always work between like hosts but + * is almost certainly broken between different host types. */ + memcpy( buf + *offset, s, sizeof(struct peer_addr)); + *offset += sizeof(struct peer_addr); return sizeof(struct peer_addr); /* bytes written */ } @@ -85,74 +89,80 @@ int marshall_peer_addr( u_int8_t * buf, const struct peer_addr * s ) /* ************************************** */ static -int marshall_uint32( u_int8_t * buf, u_int32_t val ) +int marshall_uint32( u_int8_t * buf, size_t * offset, u_int32_t val ) { - u_int32_t * nu32 = (u_int32_t *)buf; - *nu32 = htonl(val); + buf[*offset + 0] = ((val >> 24) & 0xff); + buf[*offset + 1] = ((val >> 16) & 0xff); + buf[*offset + 2] = ((val >> 8) & 0xff); + buf[*offset + 3] = ((val ) & 0xff); - return 4; + *offset += 4; + return 4; } /* ************************************** */ int marshall_n2n_packet_header( u_int8_t * buf, const struct n2n_packet_header * hdr ) { - u_int8_t * bufStart = buf; + size_t offset = 0; print_header( "Marshalling ", hdr ); - *buf = hdr->version; - ++buf; + *(buf+offset) = hdr->version; + ++offset; - *buf = hdr->msg_type; - ++buf; + *(buf+offset) = hdr->msg_type; + ++offset; - *buf = hdr->ttl; - ++buf; + *(buf+offset) = hdr->ttl; + ++offset; - *buf = hdr->sent_by_supernode; - ++buf; + *(buf+offset) = hdr->sent_by_supernode; + ++offset; - memcpy( buf, hdr->community_name, COMMUNITY_LEN ); - buf += COMMUNITY_LEN; + memcpy( buf+offset, hdr->community_name, COMMUNITY_LEN ); + offset += COMMUNITY_LEN; - memcpy( buf, hdr->src_mac, 6 ); - buf += 6; + memcpy( buf+offset, hdr->src_mac, 6 ); + offset += 6; - memcpy( buf, hdr->dst_mac, 6 ); - buf += 6; + memcpy( buf+offset, hdr->dst_mac, 6 ); + offset += 6; - buf += marshall_peer_addr( buf, &(hdr->public_ip) ); - buf += marshall_peer_addr( buf, &(hdr->private_ip) ); + marshall_peer_addr( buf, &offset, &(hdr->public_ip) ); + marshall_peer_addr( buf, &offset, &(hdr->private_ip) ); - *buf = (hdr->pkt_type & 0xff); - ++buf; + *(buf+offset) = (hdr->pkt_type & 0xff); + ++offset; - buf += marshall_uint32( buf, hdr->sequence_id ); - buf += marshall_uint32( buf, hdr->crc ); + marshall_uint32( buf, &offset, hdr->sequence_id ); + marshall_uint32( buf, &offset, hdr->crc ); - return (buf - bufStart); + return offset; } /* ************************************** */ static -int unmarshall_peer_addr( struct peer_addr * s, +int unmarshall_peer_addr( struct peer_addr * s, size_t * offset, const u_int8_t * buf ) { - memcpy(s, buf, sizeof(struct peer_addr)); - buf += sizeof(struct peer_addr); + memcpy(s, buf + *offset, sizeof(struct peer_addr)); + *offset += sizeof(struct peer_addr); return (sizeof(struct peer_addr)); /* bytes written */ } /* ************************************** */ static -int unmarshall_uint32( u_int32_t * val, const u_int8_t * buf ) +int unmarshall_uint32( u_int32_t * val, size_t * offset, const u_int8_t * buf ) { - u_int32_t * nu32 = (u_int32_t *)buf; - *val = ntohl(*nu32); + *val = ( (buf[*offset + 0] & 0xff) << 24 ); + *val |= ( (buf[*offset + 1] & 0xff) << 16 ); + *val |= ( (buf[*offset + 2] & 0xff) << 8 ); + *val |= ( (buf[*offset + 3] & 0xff) ); + *offset += 4; return 4; } @@ -160,41 +170,41 @@ int unmarshall_uint32( u_int32_t * val, const u_int8_t * buf ) int unmarshall_n2n_packet_header( struct n2n_packet_header * hdr, const u_int8_t * buf ) { - const u_int8_t * bufStart = buf; + size_t offset=0; - hdr->version = *buf; - ++buf; + hdr->version = *(buf + offset); + ++offset; - hdr->msg_type = *buf; - ++buf; + hdr->msg_type = *(buf + offset); + ++offset; - hdr->ttl = *buf; - ++buf; + hdr->ttl = *(buf + offset); + ++offset; - hdr->sent_by_supernode = *buf; - ++buf; + hdr->sent_by_supernode = *(buf + offset); + ++offset; - memcpy( hdr->community_name, buf, COMMUNITY_LEN ); - buf += COMMUNITY_LEN; + memcpy( hdr->community_name, (buf + offset), COMMUNITY_LEN ); + offset += COMMUNITY_LEN; - memcpy( hdr->src_mac, buf, 6 ); - buf += 6; + memcpy( hdr->src_mac, (buf + offset), 6 ); + offset += 6; - memcpy( hdr->dst_mac, buf, 6 ); - buf += 6; + memcpy( hdr->dst_mac, (buf + offset), 6 ); + offset += 6; - buf += unmarshall_peer_addr( &(hdr->public_ip), buf ); - buf += unmarshall_peer_addr( &(hdr->private_ip), buf ); + unmarshall_peer_addr( &(hdr->public_ip), &offset, buf ); + unmarshall_peer_addr( &(hdr->private_ip), &offset, buf ); - hdr->pkt_type = (*buf & 0xff); /* Make sure only 8 bits are copied. */ - ++buf; + hdr->pkt_type = (*(buf + offset) & 0xff); /* Make sure only 8 bits are copied. */ + ++offset; - buf += unmarshall_uint32( &(hdr->sequence_id), buf ); - buf += unmarshall_uint32( &(hdr->crc), buf ); + unmarshall_uint32( &(hdr->sequence_id), &offset, buf ); + unmarshall_uint32( &(hdr->crc), &offset, buf ); print_header( "Unmarshalled ", hdr ); - return (buf - bufStart); + return offset; } /* ************************************** */ @@ -292,7 +302,9 @@ void traceEvent(int eventTraceLevel, char* file, int line, char * format, ...) { char theDate[N2N_TRACE_DATESIZE]; char *extra_msg = ""; time_t theTime = time(NULL); - +#ifdef WIN32 + int i; +#endif /* We have two paths - one if we're logging, one if we aren't * Note that the no-log case is those systems which don't support it (WIN32), @@ -330,7 +342,8 @@ void traceEvent(int eventTraceLevel, char* file, int line, char * format, ...) { } #else /* this is the WIN32 code */ - snprintf(out_buf, sizeof(out_buf), "%s [%11s:%4d] %s%s", theDate, file, line, extra_msg, buf); + for(i=strlen(file)-1; i>0; i--) if(file[i] == '\\') { i++; break; }; + snprintf(out_buf, sizeof(out_buf), "%s [%11s:%4d] %s%s", theDate, &file[i], line, extra_msg, buf); printf("%s\n", out_buf); fflush(stdout); #endif @@ -385,7 +398,7 @@ void fill_standard_header_fields(n2n_sock_info_t * sinfo, struct n2n_packet_header *hdr, char *src_mac) { socklen_t len = sizeof(hdr->private_ip); memset(hdr, 0, N2N_PKT_HDR_SIZE); - hdr->version = N2N_VERSION; + hdr->version = N2N_PKT_VERSION; hdr->crc = 0; // FIX if(src_mac != NULL) memcpy(hdr->src_mac, src_mac, 6); getsockname(sinfo->sock, (struct sockaddr*)&hdr->private_ip, &len); @@ -405,6 +418,7 @@ void send_ack(n2n_sock_info_t * sinfo, u_int8_t pkt[ N2N_PKT_HDR_SIZE ]; size_t len = sizeof(hdr); size_t len2; + int compress_data = N2N_COMPRESSION_ENABLED; fill_standard_header_fields(sinfo, &hdr, src_mac); hdr.msg_type = MSG_TYPE_ACK_RESPONSE; @@ -414,7 +428,7 @@ void send_ack(n2n_sock_info_t * sinfo, len2=marshall_n2n_packet_header( pkt, &hdr ); assert( len2 == len ); - send_packet(sinfo, (char*)pkt, &len, remote_peer, 1); + send_packet(sinfo, (char*)pkt, &len, remote_peer, compress_data); } /* *********************************************** */ @@ -469,17 +483,26 @@ u_int receive_data(n2n_sock_info_t * sinfo, #endif return(0); } else if(len > MIN_COMPRESSED_PKT_LEN) { - char decompressed[2048]; +#define N2N_DECOMPRESS_BUFSIZE 2048 + char decompressed[N2N_DECOMPRESS_BUFSIZE]; int rc; - lzo_uint decompressed_len; + lzo_uint decompressed_len=N2N_DECOMPRESS_BUFSIZE; + size_t insize = len-N2N_PKT_HDR_SIZE; if(decompress_data) { - rc = lzo1x_decompress((u_char*)&packet[N2N_PKT_HDR_SIZE], - len-N2N_PKT_HDR_SIZE, - (u_char*)decompressed, &decompressed_len, NULL); + rc = lzo1x_decompress_safe((u_char*)&packet[N2N_PKT_HDR_SIZE], + insize, + (u_char*)decompressed, &decompressed_len, NULL); if(rc == LZO_E_OK) - traceEvent(TRACE_INFO, "%u bytes decompressed into %u", len, decompressed_len); + { + traceEvent(TRACE_INFO, "%u bytes decompressed into %u", insize, decompressed_len); + } + else + { + traceEvent(TRACE_WARNING, "Failed to decompress %u byte packet. LZO error=%d", insize, rc ); + return -1; + } if(packet_len > decompressed_len) { memcpy(&packet[N2N_PKT_HDR_SIZE], decompressed, decompressed_len); @@ -584,9 +607,9 @@ static HEAP_ALLOC(wrkmem,LZO1X_1_MEM_COMPRESS); u_int send_data(n2n_sock_info_t * sinfo, char *packet, size_t *packet_len, const struct peer_addr *to, u_int8_t compress_data) { - char compressed[1600]; + char compressed[1650]; int rc; - lzo_uint compressed_len; + lzo_uint compressed_len=0; struct sockaddr_in destsock; if(*packet_len < N2N_PKT_HDR_SIZE) { @@ -603,6 +626,13 @@ u_int send_data(n2n_sock_info_t * sinfo, *packet_len - N2N_PKT_HDR_SIZE, (u_char*)&compressed[N2N_PKT_HDR_SIZE], &compressed_len, wrkmem); + + if ( 0 == compressed_len ) + { + traceEvent(TRACE_WARNING, "failed to compress %u bytes.", (*packet_len - N2N_PKT_HDR_SIZE) ); + return -1; + } + compressed_len += N2N_PKT_HDR_SIZE; traceEvent(TRACE_INFO, "%u bytes compressed into %u", *packet_len, compressed_len); diff --git a/n2n.h b/n2n.h index aaded83..e5fa8e0 100644 --- a/n2n.h +++ b/n2n.h @@ -1,5 +1,6 @@ /* - * (C) 2007-08 - Luca Deri + * (C) 2007-09 - Luca Deri + * Richard Andrews * * 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 @@ -15,7 +16,6 @@ * along with this program; if not, see * * Code contributions courtesy of: - * Richard Andrews * Babak Farrokhi [FreeBSD port] * */ @@ -113,7 +113,7 @@ typedef struct tuntap_dev { #endif /* #ifndef WIN32 */ #define QUICKLZ 1 -#define N2N_VERSION 1 +#define N2N_PKT_VERSION 1 #define MSG_TYPE_REGISTER 1 /* FIX invece di usare il sender del pacchetto scriverlo nel pacchetto stesso */ #define MSG_TYPE_DEREGISTER 2 @@ -124,6 +124,14 @@ typedef struct tuntap_dev { #define COMMUNITY_LEN 16 #define MIN_COMPRESSED_PKT_LEN 32 +/* Set N2N_COMPRESSION_ENABLED to 0 to disable lzo1x compression of ethernet + * frames. Doing this will break compatibility with the standard n2n packet + * format so do it only for experimentation. All edges must be built with the + * same value if they are to understand each other. */ +#define N2N_COMPRESSION_ENABLED 1 + +#define DEFAULT_MTU 1400 + /* Maximum enum value is 255 due to marshalling into 1 byte */ enum packet_type { packet_unreliable_data = 0, /* no ACK needed */ @@ -234,7 +242,8 @@ extern void send_ack(n2n_sock_info_t * sinfo, char *src_mac); extern void traceEvent(int eventTraceLevel, char* file, int line, char * format, ...); -extern int tuntap_open(tuntap_dev *device, char *dev, char *device_ip, char *device_mask, const char * device_mac ); +extern int tuntap_open(tuntap_dev *device, char *dev, char *device_ip, + char *device_mask, const char * device_mac, int mtu); extern int tuntap_read(struct tuntap_dev *tuntap, unsigned char *buf, int len); extern int tuntap_write(struct tuntap_dev *tuntap, unsigned char *buf, int len); extern void tuntap_close(struct tuntap_dev *tuntap); diff --git a/n2n.spec b/n2n.spec index 8eede44..0e7892a 100644 --- a/n2n.spec +++ b/n2n.spec @@ -1,6 +1,6 @@ Summary: N2N peer-to-peer virtual private network system. Name: n2n -Version: 1.2 +Version: 1.3 Release: 1 License: GPLv3 Vendor: ntop.org diff --git a/scripts/mk_tar.sh b/scripts/mk_tar.sh index 347191b..539a565 100755 --- a/scripts/mk_tar.sh +++ b/scripts/mk_tar.sh @@ -22,7 +22,7 @@ function exit_fail() } PACKAGE="n2n" -PKG_VERSION="1.2" +PKG_VERSION="1.3" PKG_AND_VERSION="${PACKAGE}-${PKG_VERSION}" TEMPDIR="tmp" @@ -50,7 +50,6 @@ debian/changelog debian/compat debian/control debian/copyright -debian/files debian/n2n.dirs debian/n2n.docs debian/n2n.install @@ -62,7 +61,7 @@ debian/rules BASE=`pwd` for F in ${SOURCE_MANIFEST}; do - test -e $F || exit_fail "Wrong directory. Please execute from n2n directory."; >&2 + test -e $F || exit_fail "Cannot find $F. Maybe you're in the wrong directory. Please execute from n2n directory."; >&2 done echo "Found critical files. Proceeding." >&2 diff --git a/supernode.1 b/supernode.1 index 808f803..863c498 100644 --- a/supernode.1 +++ b/supernode.1 @@ -1,4 +1,4 @@ -.TH supernode 1 "May 3, 2008" "revision 3472" "USER COMMANDS" +.TH supernode 1 "Jan 3, 2009" "revision 3679" "USER COMMANDS" .SH NAME supernode \- n2n supernode daemon .SH SYNOPSIS @@ -12,11 +12,15 @@ packets only between members of the same community. The supernode does not hold the community encryption key and so cannot snoop or inject packets into the community. .PP +Supernode can service a number of n2n communities concurrently. Traffic does not +cross between communities. +.PP All logging goes to stdout. .SH OPTIONS .TP -\-l +\-l listen on the given UDP port +.TP \-v use verbose logging .SH EXAMPLES @@ -24,9 +28,13 @@ use verbose logging .B supernode -l 7654 -v Start supernode listening on UDP port 7654 with verbose output. .PP +.SH RESTART +When suprenode restarts it loses all registration information from associated +edge nodes. It can take up to five minutes for the edge nodes to re-register and +normal traffic flow to resume. .SH EXIT STATUS -edge is a daemon and any exit is an error +supernode is a daemon and any exit is an error .SH AUTHOR Luca Deri ( deri (at) ntop.org ), Richard Andrews ( andrews (at) ntop.org ), Don Bindner .SH SEE ALSO -ifconfig(1) edge(1) +ifconfig(8) edge(8) diff --git a/supernode.c b/supernode.c index 4031472..ff41927 100644 --- a/supernode.c +++ b/supernode.c @@ -1,5 +1,6 @@ /* - * (C) 2007-08 - Luca Deri + * (C) 2007-09 - Luca Deri + * Richard Andrews * * 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 @@ -14,9 +15,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, see * - * Code contributions courtesy of: - * Richard Andrews - * */ #include "n2n.h" @@ -65,7 +63,7 @@ static void send_register_ack( n2n_sock_info_t * sinfo, /* leave IP sockets unfilled. */ marshall_n2n_packet_header( pkt, &hdr ); - send_packet(sinfo, (char *)pkt, &len, destination_peer, 1); + send_packet(sinfo, (char *)pkt, &len, destination_peer, N2N_COMPRESSION_ENABLED); } static void register_peer(struct n2n_packet_header *hdr, @@ -90,7 +88,7 @@ static void register_peer(struct n2n_packet_header *hdr, memcpy(&scan->private_ip, &hdr->private_ip, sizeof(struct peer_addr)); /* Overwrite existing peer */ - traceEvent(TRACE_NORMAL, "Re-registered node [public_ip=(%d)%s:%d][private_ip=%s:%d][mac=%s][community=%s]", + traceEvent(TRACE_NORMAL, "Re-registered node [public_ip=(%d)%s:%hd][private_ip=%s:%hd][mac=%s][community=%s]", scan->public_ip.family, intoa(ntohl(scan->public_ip.addr_type.v4_addr), buf, sizeof(buf)), ntohs(scan->public_ip.port), @@ -144,7 +142,7 @@ static void deregister_peer(struct n2n_packet_header *hdr, else prev->next = scan->next; - traceEvent(TRACE_INFO, "Degistered node [public_ip=%s:%d][private_ip=%s:%d]", + traceEvent(TRACE_INFO, "Degistered node [public_ip=%s:%hd][private_ip=%s:%hd]", intoa(ntohl(scan->public_ip.addr_type.v4_addr), buf, sizeof(buf)), ntohs(scan->public_ip.port), intoa(ntohl(scan->private_ip.addr_type.v4_addr), buf1, sizeof(buf1)), @@ -157,7 +155,7 @@ static void deregister_peer(struct n2n_packet_header *hdr, scan = scan->next; } - traceEvent(TRACE_WARNING, "Unable to delete specified peer [%s:%d]", + traceEvent(TRACE_WARNING, "Unable to delete specified peer [%s:%hd]", intoa(ntohl(sender->addr_type.v4_addr), buf, sizeof(buf)), ntohs(sender->port)); } @@ -213,7 +211,7 @@ static size_t broadcast_packet(char *packet, u_int packet_len, ++numsent; ++(supernode_stats.pkts); - traceEvent(TRACE_INFO, "Sent multicast message to remote node [%s:%d][mac=%s]", + traceEvent(TRACE_INFO, "Sent multicast message to remote node [%s:%hd][mac=%s]", intoa(ntohl(scan->public_ip.addr_type.v4_addr), buf, sizeof(buf)), ntohs(scan->public_ip.port), macaddr_str(scan->mac_addr, buf1, sizeof(buf1))); @@ -287,7 +285,7 @@ static size_t forward_packet(char *packet, u_int packet_len, } else { ++(supernode_stats.pkts); - traceEvent(TRACE_INFO, "Sent message to remote node [%s:%d][mac=%s]", + traceEvent(TRACE_INFO, "Sent message to remote node [%s:%hd][mac=%s]", intoa(ntohl(scan->public_ip.addr_type.v4_addr), buf, sizeof(buf)), ntohs(scan->public_ip.port), macaddr_str(scan->mac_addr, buf1, sizeof(buf1))); @@ -311,7 +309,7 @@ static void handle_packet(char *packet, u_int packet_len, n2n_sock_info_t * sinfo) { ipstr_t buf; - traceEvent(TRACE_INFO, "Received message from node [%s:%d]", + traceEvent(TRACE_INFO, "Received message from node [%s:%hd]", intoa(ntohl(sender->addr_type.v4_addr), buf, sizeof(buf)), ntohs(sender->port)); @@ -323,7 +321,7 @@ static void handle_packet(char *packet, u_int packet_len, unmarshall_n2n_packet_header( hdr, (u_int8_t *)packet ); - if(hdr->version != N2N_VERSION) { + if(hdr->version != N2N_PKT_VERSION) { traceEvent(TRACE_WARNING, "Received packet with unknown protocol version (%d): discarded\n", hdr->version); @@ -445,6 +443,10 @@ int main(int argc, char* argv[]) { n2n_sock_info_t udp_sinfo; n2n_sock_info_t tcp_sinfo; +#ifdef WIN32 + initWin32(); +#endif + optarg = NULL; while((opt = getopt_long(argc, argv, "l:vh", long_options, NULL)) != EOF) { switch (opt) { diff --git a/tuntap_freebsd.c b/tuntap_freebsd.c index f4a03a8..95308be 100644 --- a/tuntap_freebsd.c +++ b/tuntap_freebsd.c @@ -1,5 +1,5 @@ /* - * (C) 2007-08 - Luca Deri + * (C) 2007-09 - Luca Deri * * 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 @@ -28,7 +28,8 @@ int tuntap_open(tuntap_dev *device /* ignored */, char *dev, char *device_ip, char *device_mask, - const char * device_mac ) { + const char * device_mac, + int mtu) { int i; char tap_device[N2N_FREEBSD_TAPDEVICE_SIZE]; @@ -61,8 +62,8 @@ int tuntap_open(tuntap_dev *device /* ignored */, system(buf); } - snprintf(buf, sizeof(buf), "ifconfig tap%d %s netmask %s mtu 1400 up", - i, device_ip, device_mask); + snprintf(buf, sizeof(buf), "ifconfig tap%d %s netmask %s mtu %d up", + i, device_ip, device_mask, mtu); system(buf); traceEvent(TRACE_NORMAL, "Interface tap%d up and running (%s/%s)", diff --git a/tuntap_linux.c b/tuntap_linux.c index 7e90ea6..a1d20fb 100644 --- a/tuntap_linux.c +++ b/tuntap_linux.c @@ -1,5 +1,5 @@ /* - * (C) 2007-08 - Luca Deri + * (C) 2007-09 - Luca Deri * * 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 @@ -42,6 +42,7 @@ static void read_mac(char *ifname, char *mac_addr) { } /* ********************************** */ + /** @brief Open and configure the TAP device for packet read/write. * * This routine creates the interface via the tuntap driver then uses ifconfig @@ -52,6 +53,7 @@ static void read_mac(char *ifname, char *mac_addr) { * if NULL system will assign a name * @param device_ip - address of iface * @param device_mask - netmask for device_ip + * @param mtu - MTU for device_ip * * @return - negative value on error * - non-negative file-descriptor on success @@ -60,7 +62,8 @@ int tuntap_open(tuntap_dev *device, char *dev, /* user-definable interface name, eg. edge0 */ char *device_ip, char *device_mask, - const char * device_mac ) { + const char * device_mac, + int mtu) { char *tuntap_device = "/dev/net/tun"; #define N2N_LINUX_SYSTEMCMD_SIZE 128 char buf[N2N_LINUX_SYSTEMCMD_SIZE]; @@ -69,7 +72,7 @@ int tuntap_open(tuntap_dev *device, device->fd = open(tuntap_device, O_RDWR); if(device->fd < 0) { - printf("ERROR: ioctl() [%s][%d]\n", strerror(errno), rc); + printf("ERROR: ioctl() [%s][%d]\n", strerror(errno), errno); return -1; } @@ -84,10 +87,6 @@ int tuntap_open(tuntap_dev *device, return -1; } - /* REVISIT: BbMja7: MTU should be related to MTU of the interface the tuntap - * is built on. The value 1400 assumes an eth iface with MTU 1500, but would - * fail for ppp at mtu=576. - */ if ( device_mac ) { /* Set the hw address before bringing the if up. */ @@ -97,12 +96,13 @@ int tuntap_open(tuntap_dev *device, traceEvent(TRACE_INFO, "Setting MAC: %s", buf); } - snprintf(buf, sizeof(buf), "/sbin/ifconfig %s %s netmask %s mtu 1400 up", - ifr.ifr_name, device_ip, device_mask); + snprintf(buf, sizeof(buf), "/sbin/ifconfig %s %s netmask %s mtu %d up", + ifr.ifr_name, device_ip, device_mask, mtu); system(buf); traceEvent(TRACE_INFO, "Bringing up: %s", buf); device->ip_addr = inet_addr(device_ip); + device->device_mask = inet_addr(device_mask); read_mac(dev, (char*)device->mac_addr); return(device->fd); } diff --git a/tuntap_osx.c b/tuntap_osx.c index be8b312..c0c4c08 100644 --- a/tuntap_osx.c +++ b/tuntap_osx.c @@ -1,5 +1,5 @@ /* - * (C) 2007-08 - Luca Deri + * (C) 2007-09 - Luca Deri * * 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 @@ -28,7 +28,8 @@ int tuntap_open(tuntap_dev *device /* ignored */, char *dev, char *device_ip, char *device_mask, - const char * device_mac ) { + const char * device_mac, + int mtu) { int i; char tap_device[N2N_OSX_TAPDEVICE_SIZE]; @@ -61,8 +62,8 @@ int tuntap_open(tuntap_dev *device /* ignored */, system(buf); } - snprintf(buf, sizeof(buf), "ifconfig tap%d %s netmask %s mtu 1400 up", - i, device_ip, device_mask); + snprintf(buf, sizeof(buf), "ifconfig tap%d %s netmask %s mtu %d up", + i, device_ip, device_mask, mtu); system(buf); traceEvent(TRACE_NORMAL, "Interface tap%d up and running (%s/%s)", @@ -89,7 +90,7 @@ int tuntap_open(tuntap_dev *device /* ignored */, exit(0); } - traceEvent(TRACE_NORMAL, "Interface tap%d mac %s", i, buf); + traceEvent(TRACE_NORMAL, "Interface tap%d [MTU %d] mac %s", i, mtu, buf); if(sscanf(buf, "%02x:%02x:%02x:%02x:%02x:%02x", &a, &b, &c, &d, &e, &f) == 6) { device->mac_addr[0] = a, device->mac_addr[1] = b; device->mac_addr[2] = c, device->mac_addr[3] = d;