patch for tinc-0.3

Hans Bayle hansb at direct.a2000.nl
Wed Oct 20 12:37:02 CEST 1999


Hi tinc list members,

There were some problems with Ivo's email adresses (both zarq at iname.com
and 
zarq at spark.icicle.dhs.org) so I resent the stuff to the mailling list.


=============================================

                    

Hi Ivo,

Hier is een oplossing voor een bugje in flush_queue(), en ook wat andere
troepjes
zoals een tincd scheduler. Dit werkt wat beter, omdat de scheduler een
afzonderlijk
programma is, en niet meecrashed als tincd down gaat.

Heb alleen nog wel het gevoel dat de ping test in het tincsched soms wat
al te
snel denkt dat er geen verbinding is, ik ga er nog es verder naar
kijken.

Volgens raakt de queue corrupt, omdat bij flush_queue() de rq->tail
pointer
niet goed wordt gezet na afloop.

Ik check in xrec() voor het crypten of het packet misschien corrupt is
door te kijken
of de grootte van het packet klopt - een slecht soort checksun.
Als het niet klopt, wat doe je in zo'n geval, het packet droppen? Want
nu blijft het in de queue zitten.

Greetingz -- hansb
-------------- next part --------------
Only in tinc-0.3-patched: Makefile
Only in tinc-0.3-patched/cipher: Makefile
Only in tinc-0.3-patched/cipher/blowfish: Makefile
diff -r tinc-0.3/cipher/blowfish/bf_cfb64.c tinc-0.3-patched/cipher/blowfish/bf_cfb64.c
60a61
> #include <syslog.h>
75a77
> 
diff -r tinc-0.3/cipher/cipher.c tinc-0.3-patched/cipher/cipher.c
19a20,21
> #include <stdio.h>
> 
32a35,36
> void fdump(FILE *, char *, int);
> 
46c50,53
< 
---
>   if (debug_lvl > 3) {
>     syslog(LOG_ERR, "about to blowfish_cfb64");
>     syslog(LOG_ERR, "length in packet: %ld", len);
>   }
47a55,57
>   if (debug_lvl > 3) {
>     syslog(LOG_ERR, "done blowfish_cfb64");
>   }
54a65,68
>   if (debug_lvl > 10) {
> fdump(stdout, in, in->len);   
>   }
> 
76a91,92
> 
> 
107a124,151
> 
> /*
>  *      fdump.c -- Dump memory in debug format.
>  *
>  *      Compile separately and link to program,
>  *      or just include this file.
>  *
>  */
> void fdump(FILE *stream, char *adr,int bytecount)
> {
>         int i,j, linecount;
>         char asc_str[17];
>         unsigned char c;
>         linecount = (bytecount + 15) / 16;
>         asc_str[16] = '\0';
>         for(j=0; j<linecount; j++) {
>             fprintf(stream, "\n%06d ", adr+16*j);
>             for(i=0; i<16; i++) {
>                 c = *(adr+16*j+i);
>                 asc_str[i] = (c >= 32 && c < 128) ? c : '.';
>                 fprintf(stream, "%c%02X", (i==8) ? '-' : ' ', (int) c);
>             }
>             fprintf(stream, "    %s", asc_str);
>         }
>         fprintf(stream, "\n");
> }
> /* end of fdump.c */
> 
Only in tinc-0.3-patched/cipher/idea: Makefile
Only in tinc-0.3-patched: config.cache
Only in tinc-0.3-patched: config.h
Only in tinc-0.3-patched: config.log
Only in tinc-0.3-patched: config.status
Only in tinc-0.3-patched/doc: Makefile
diff -r tinc-0.3/doc/tincd.8 tinc-0.3-patched/doc/tincd.8
2c2
< .TH TINC 1 "August 1999" "tinc version 0.3" "FSF"
---
> .TH TINC 1 "October 1999" "tinc version 0.3" "FSF"
Only in tinc-0.3-patched/lib: Makefile
Only in tinc-0.3-patched: libtool
Only in tinc-0.3-patched/m4: Makefile
Only in tinc-0.3-patched: misc
Only in tinc-0.3-patched/src: Makefile
Only in tinc-0.3-patched/src: bla
diff -r tinc-0.3/src/net.c tinc-0.3-patched/src/net.c
129a130,132
> /*
>  * decrypt received udp packet, and write into tap device
>  */
132a136
>   real_packet_t *rp_ptr;
133a138,146
>   int rp_lenin;
> 
>   rp_lenin = ((real_packet_t *) packet)->data.len;
> 
>   /* encryption will crash when packet has unexpected len */
>   if ( ! ((rp_lenin > 20) && (rp_lenin < MAXSIZE))) {
>     syslog(LOG_ERR, "dropping strange packet len: %d", rp_lenin);
>     return 1;
>   } 
140c153
<   else
---
>   else {
141a155,156
>     if(debug_lvl > 3) syslog(LOG_DEBUG, "writing in tap - %d - %d", vp.len + 2, lenin);
>   }
154,155c169,178
<   if(debug_lvl > 3)
<     syslog(LOG_DEBUG, "packet to queue: %d", s);
---
>   if(debug_lvl > 3) {
>     syslog(LOG_DEBUG, "packet to queue: %d", s - 2);
> dump_pkt_queue(*q);
>     if (*q) {
>   if((*q)->head)
>     syslog(LOG_DEBUG, "head != NULL");
>   if((*q)->tail)
>     syslog(LOG_DEBUG, "tail != NULL");
>     }
>    }
159a183
> 
167a192
> 
171a197
> 
183a210,211
>   int i=0;
>   real_packet_t *vp;
185a214,217
>   if(debug_lvl > 3) {
>   dump_conn_list();
>   }
> 
187a220,223
>       i++;
>       vp = (real_packet_t *) p->packet;
>       if(debug_lvl > 1) syslog(LOG_DEBUG, "flushing packet %d len: %d", i, vp->len);
> 
190d225
< cp
192c227
<         {
---
>         { /* returned zero: remove packet and queue elem */
198c233,234
< cp
---
>           if(debug_lvl > 1) syslog(LOG_DEBUG, "freeing packet %d ", i);
> 
200d235
< cp
202d236
< cp
204a239
>         {
206c241
< cp
---
>         }
209a245,252
>   
>   /* adjust to last element left in queue */
>   if (prev)
>       pq->tail = prev;
>   else {
>       pq->tail = NULL;
>       pq->head = NULL;
>   }
222d264
< cp
228a271,272
>       if(debug_lvl > 1)
> dump_pkt_queue(cl->sq);
230d273
< cp
237a281,282
>       if(debug_lvl > 1)
> dump_pkt_queue(cl->rq);
239d283
< cp
267a312,313
>       if(debug_lvl > 1)
> dump_pkt_queue(cl->sq);
268a315,316
>       if(debug_lvl > 1)
> dump_pkt_queue(cl->sq);
276a325,326
>       if(debug_lvl > 1)
> dump_pkt_queue(cl->sq);
278a329,330
> dump_pkt_queue(cl->sq);
>       if(debug_lvl > 1)
768a821
> dump_pkt_queue(f->rq);
769a823
> dump_pkt_queue(f->rq);
Only in tinc-0.3-patched/src: net.c.org
diff -r tinc-0.3/src/netutl.c tinc-0.3-patched/src/netutl.c
219a220,238
> void dump_pkt_queue(packet_queue_t *pq)
> {
>   int i=0;
>   real_packet_t *vp;
>   queue_element_t *p, *q;
> 
>   if(debug_lvl > 1) syslog(LOG_DEBUG, "dumping queue");
> 
>   if (!pq) return;
> 
>   for(p = pq->head; p != NULL; p = q)
>     {
>       i++;
>       vp = (real_packet_t *) p->packet;
>       if(debug_lvl > 1) syslog(LOG_DEBUG, "queue has packet %d len: %d", i, vp->len);
>       q = p->next;
>     }
> }
> 
diff -r tinc-0.3/src/netutl.h tinc-0.3-patched/src/netutl.h
33a34
> extern void dump_pkt_queue(packet_queue_t *);
diff -r tinc-0.3/src/tincd.c tinc-0.3-patched/src/tincd.c
429a430,431
> /* looping sigsegv handler: want a core dump */
> /*
431a434
> */
Only in tinc-0.3-patched: stamp-h


-------------- next part --------------
#!/usr/bin/perl
#
#
# program that schedules tincd
#
# watches if it is up
# watches if there is a connection

use POSIX;
require 'timelocal.pl';
use Sys::Syslog  qw(:DEFAULT setlogsock);
use Sys::Hostname;
use Net::Ping;

$HOME="/usr/local/etc/tinc";
$LOGDIR="/var/log";
$PROGNAME="tincsched";
$TESTHOST="a2000-gw1.aie.nl";

$host = $TESTHOST;
$oldmsg = "";
$0 = $PROGNAME; # cant get `ps -ef` show my progname ):

&check_pid("$HOME/tincsched.pid", $$);

&redir_io_log($PROGNAME);

write_syslog('info', "$PROGNAME started with pid $$ \n");

$SIG{'CHLD'} = 'handler';
$SIG{'TERM'} = 'sigtermhandler';
chdir("$HOME") || die "Can't chdir to $HOME";

$p = Net::Ping->new("icmp");


# endless loop
while (1) { 
    #
    # check if in the process table
    $result = `ps auwx | grep tincd | grep -v grep`;
    if (!$result) {
	write_syslog('info', "$PROGNAME: tincd not running, restarting tincd \n");
        $cmd = "/etc/rc.d/init.d/tinc starttinc";
        system($cmd);
	sleep 30; # 15 secs
    }

    # check if there is a connection
    if (!$p->ping($host, 30)) {
	write_syslog('info', "$PROGNAME: connection loss, stopping tincd \n");
        $cmd = "/etc/rc.d/init.d/tinc stoptinc";
        system($cmd);
	sleep 3; # 15 secs
	write_syslog('info', "$PROGNAME: connection loss, restarting tincd \n");
        $cmd = "/etc/rc.d/init.d/tinc starttinc";
        system($cmd);
	sleep 30; # 15 secs
    }

    sleep 30; # 15 secs
}

close(OUT);

exit 0;


sub redir_io_log {
    local($name) = @_;
    # do not buffer io
    select((select(STDOUT), $| = 1)[0]);
    select((select(STDERR), $| = 1)[0]);

    # redirect stdout and stderr
    open(STDOUT, ">>$LOGDIR/tinc.log");
    open(STDERR, ">&STDOUT");
}


sub print_log {
    ($tsec,$tmin,$thour,$mday, $mon,$year,$rest) = localtime(time());

    $monno = $mon + 1;
    if ($monno<10) {
	$monno = "0$monno";
    }
    if ($mday<10) {
	$mday = "0$mday";
    }
    if ($year > 99) {
	$yearno = "20" . $year;
    } else {
	$yearno = "19" . $year;
    }

    $time = sprintf("%2.2d-%2.2d-%2.2d %2.2d:%2.2d:%2.2d",$year,$monno,$mday,
	$thour, $tmin, $tsec);
    print("$time $$ @_");
}


sub write_syslog {
    local($pri, $message) = @_;
   
    setlogsock ('unix');
#print "write_syslog(local): pri: <$pri> message: <$message>\n";

    # progname, logto console if not succeed / write the pid, facility
#print "write_syslog(openlog): PROGNAME: <$PROGNAME>\n";
    openlog($PROGNAME, 'cons, pid, nowait', 'daemon');

    # priority, message strings
#print "write_syslog(syslog): pri: <$pri> message: <$message>\n";
    syslog($pri, $message);

    # close the log
    closelog();
}



sub write_pid {
    local($file, $pid) = @_;
    open(LOCK, ">$file");
    print LOCK "$pid\n";
    close(LOCK);
}

sub rm_lock {
    local($file, $pid) = @_;
    unlink($file);
}

sub check_pid {
    local($file, $pid) = @_;
    if (-e $file) {
	#uhoh file exists...
	open(LOCK, "<$file");
	$foreignpid = <LOCK>;
	chop($foreignpid);
	close(LOCK);


	#valid pid?
	if ($foreignpid) {

	    print "tincsched: saw an old lockfile with pid $foreignpid\n";
	    write_syslog('info', "tincsched: saw an old lockfile with pid $foreignpid\n");

	    $fpids = `ps -ef | grep "/usr/bin/perl /dev/fd" | grep -v grep | /bin/sed -e 's/ *[a-z0-9]*  *//' -e 's/ .*//'`;
	    @the_running_pids = split /\n/, $fpids;

	    $found=0;
	    foreach $rpid (@the_running_pids) {
		if ($foreignpid == $rpid) {
			$found=1;
		}
	    }
	} else {
	    write_pid($file, $pid);
	    return;
	}

	if ($found) {
	    foreach $rpid (@the_running_pids) {
		if ($foreignpid == $rpid) {
			write_syslog('info', "tincsched: tincsched [$rpid] is already running.\n");
			die("tincsched: tincsched [$rpid] is already running.\n");
		}
	    }
	} else {
	    write_syslog('info', "tincsched: $foreignpid doesn't run, overwriting lockfile .\n");
	    print "tincsched: $foreignpid doesn't run, overwriting lockfile .\n";
	    write_pid($file, $pid);
	    return;
	}
    } else {
	write_pid($file, $pid);
	return;
    }
}


sub handler {
    local($sig) = @_;


    $childpid = waitpid(-1, 1);

    if ($children{$childpid}) {
	print "tincsched: Caught a SIG$sig\n";
	write_syslog('info', "Caught a SIG$sig\n");

	print "Child had pid $childpid, $children{$childpid} is ready for deletion.\n";
	write_syslog('info', "Child had pid $childpid, deleting $children{$childpid}\n");

	delete $children{$childpid};
    } else {
#	print "tincsched: $childpid not spawned by me.\n";
#	write_syslog('info', "$childpid not spawned by me.\n");
    }
    1;
}


sub sigtermhandler {
    local($sig) = @_;

    print "tincsched: Caught a SIG$sig\n";
    write_syslog('info', "tincsched: Caught a SIG$sig\n");

    foreach $key (keys %children) {

	print "tincsched: killing child $key\n";
	write_syslog('info', "tincsched: killing child $key\n");

	kill 15, $key;
    }

    print "tincsched: Removing lockfile\n";
    write_syslog('info', "tincsched: Removing lockfile\n");
    
    &rm_lock("$HOME/ipmkbs.pid", $$);

    print "tincsched: terminating\n";
    write_syslog('info', "tincsched: terminating\n");

    exit(0);
    1;
}

sub lock_file {
    local($path) = @_;


    $lock_status = 0;
    #
    # WHOOPS.. open the filehandle NON destructive
    #
    $open_status = open(FDESCRIPTOR, "+>>$path");
    if ($open_status) {

	#
	# now test AND lock if test succeeds
	#
	if (File::lockf::tlock(FDESCRIPTOR) == EAGAIN) {
	    # wait for the next main loop cycle
	    $lock_status = 0;
	    write_syslog('info', "IPMKBS: $qfile $path locked by sendmail.\n");
	    close(FDESCRIPTOR);
	} else {
	    # got the lock here
	    $lock_status = 1;
	    write_syslog('info', "IPMKBS: $qfile $path locked by me.\n");
	}
    } else {
	    # hmm.. must be in use
	    write_syslog('info', "IPMKBS: $qfile $path locked by sendmail?\n");
    }
    return $lock_status;
}



sub unlock_file {
    local($path) = @_;
    if ($lock_status) {
	$open_status = open(FDESCRIPTOR, "+>>$path");
	if ($open_status) {
	    File::lockf::ulock(FDESCRIPTOR);
	    close(FDESCRIPTOR);
	    write_syslog('info', "IPMKBS: $qfile $path unlocked.\n");
	} else {
	    write_syslog('info', "IPMKBS: $qfile WHOOPS Cant get a FH for $path.\n");
	}
    }
}


-------------- next part --------------
#!/bin/sh
#
#
#
# Source function library
. /etc/rc.d/init.d/functions

# dump core
ulimit -c 10000000

# See how we were called.
case "$1" in
  start)
	echo -n "Starting up tinc system... "
        /bin/rm -f /core
	ifconfig tap0 down
#	ifconfig tap0 hw ether fe:fd:c0:a8:0a:02
	ifconfig tap0 hw ether fe:fd:c0:a8:0a:02
	ifconfig tap0 up
#	route add  -net 193.78.1.0/24 gw 193.78.1.82
	route add  -host 193.78.1.4 gw 193.78.1.82
	route add  -host 193.78.1.9 gw 193.78.1.82
	route add  -host 193.78.1.15 gw 193.78.1.82
	route add  -host 193.78.1.18 gw 193.78.1.82
	/usr/local/sbin/tincd -n fui-vpn
#	/usr/local/sbin/tincd -d -d -d -d -d -d -n fui-vpn
        /usr/local/sbin/tincsched &
	touch /var/lock/subsys/tinc
	echo done
	;;
  starttinc)
	echo -n "Starting up tinc only... "
        /bin/rm -f /core
#	route add  -net 193.78.1.0/24 gw 193.78.1.82
	route add  -host 193.78.1.4 gw 193.78.1.82
	route add  -host 193.78.1.9 gw 193.78.1.82
	route add  -host 193.78.1.18 gw 193.78.1.82
	route add  -host 193.78.1.15 gw 193.78.1.82
	/usr/local/sbin/tincd -n fui-vpn
#	/usr/local/sbin/tincd -d -d -d -d -d -d -n fui-vpn
	touch /var/lock/subsys/tinco
	echo done
	;;
  stoptinc)
	echo -n "Shutting down tinc only..."
	/usr/local/sbin/tincd -k -n fui-vpn
	rm -f /var/log/subsys/tinco
	echo
	;;
  stop)
	echo -n "Shutting down all tinc..."
        killall tincsched
	route del  -host 193.78.1.9 gw 193.78.1.82
	route del  -host 193.78.1.18 gw 193.78.1.82
	route del  -host 193.78.1.15 gw 193.78.1.82
	/usr/local/sbin/tincd -k -n fui-vpn
	ifconfig tap0 down
	rm -f /var/log/subsys/tinc
	echo
	;;
  status)
	status tinc
	;;
  restart|reload)
	$0 stop
	$0 start
	;;
esac

exit 0





More information about the Tinc mailing list