Package: release.debian.org
Severity: normal
User: release.debian.org@packages.debian.org
Usertags: unblock
Regards,
Please unblock pptpd (1.4.0-5)
The differences to the jessie version 1.4.0-3 are:
* -4 fixed an important bug where overlong interface names
might crash the bcrelay program (#765442)
* -5 fixed the patch description, that was an error on my side and I'd
really like to see the wrong attribution removed.
The debdiff is attached. It got a bit bigger since upstream decided to
re-arrange the affected code.
If you want to take a closer look, the upstream commit IDs are part of the
path, upstream git is at
git://git.code.sf.net/p/poptop/git
Regards,
Christoph
-- System Information:
Debian Release: jessie/sid
APT prefers testing
APT policy: (500, 'testing')
Architecture: amd64 (x86_64)
Kernel: Linux 3.17.4 (SMP w/4 CPU cores; PREEMPT)
Locale: LANG=C, LC_CTYPE=C (charmap=ANSI_X3.4-1968)
Shell: /bin/sh linked to /bin/dash
diff -Nru pptpd-1.4.0/debian/changelog pptpd-1.4.0/debian/changelog
--- pptpd-1.4.0/debian/changelog 2014-07-15 18:41:01.000000000 +0200
+++ pptpd-1.4.0/debian/changelog 2014-11-04 23:41:32.000000000 +0100
@@ -1,3 +1,17 @@
+pptpd (1.4.0-5) unstable; urgency=medium
+
+ * Fix description of patch introduced in 1.4.0-4
+
+ -- Christoph Biedl <debian.axhn@manchmal.in-ulm.de> Tue, 04 Nov 2014 23:30:46 +0100
+
+pptpd (1.4.0-4) unstable; urgency=medium
+
+ * Fix buffer overflow from overlong interface names in bcrelay.
+ Closes: #765442
+ * Fixes an important bug, urgency set to medium
+
+ -- Christoph Biedl <debian.axhn@manchmal.in-ulm.de> Sun, 26 Oct 2014 20:50:20 +0100
+
pptpd (1.4.0-3) unstable; urgency=low
* Fix status check in init script. Closes: #747146
diff -Nru pptpd-1.4.0/debian/patches/cherry-pick.1.4.0-11-g4ea2db6.ff.patch pptpd-1.4.0/debian/patches/cherry-pick.1.4.0-11-g4ea2db6.ff.patch
--- pptpd-1.4.0/debian/patches/cherry-pick.1.4.0-11-g4ea2db6.ff.patch 1970-01-01 01:00:00.000000000 +0100
+++ pptpd-1.4.0/debian/patches/cherry-pick.1.4.0-11-g4ea2db6.ff.patch 2014-11-04 23:40:37.000000000 +0100
@@ -0,0 +1,1479 @@
+Subject: Cherry-pick 1.4.0-11-g4ea2db6 ff. to fix sprintf usage
+Author: James Cameron <quozl@laptop.org>
+Date: Thu Oct 16 08:22:36 2014 +1100
+Origin:
+ commit 4ea2db6028cc1079aa84ac1b92e23ba8a7ce9d8e
+ commit 2521c45c19106722f299c66d4e0ef86ff7486b54
+ commit eee8ad1adece7cc5dfcadaa3cf838cfaf0b01b05
+Bug-Debian: https://bugs.debian.org/765442
+Last-Update: 2014-10-25
+
+--- a/bcrelay.c
++++ b/bcrelay.c
+@@ -1,6 +1,6 @@
+-// A broadcast packet repeater. This packet repeater (currently designed for
+-// udp packets) will listen for broadcast packets.
+-// When it receives the packets, it will then re-broadcast the packet.
++// A broadcast packet repeater. This packet repeater (currently
++// designed for udp packets) will listen for broadcast packets. When
++// it receives the packets, it will then re-broadcast the packet.
+ //
+ // Written by TheyCallMeLuc(at)yahoo.com.au
+ // I accept no responsiblity for the function of this program if you
+@@ -8,58 +8,70 @@
+ // Modified for Poptop by Richard de Vroede <r.devroede@linvision.com>
+ // Ditto on the no responsibility.
+ //
+-// Rewritten by Norbert van Bolhuis <norbert@vanbolhuis.demon.nl> bcrelay (v1.0+)
+-// now supports/does:
+-// 1) Relaying from PPP (VPN tunnel) interfaces, hereby creating a virtual
+-// LAN (w.r.t. UDP broadcasts) for VPN clients and ethernet PCs
+-// belonging/matching the subnet portion of the VPN IP addresses.
+-// So now broadcasting to/from all systems of the VPN has been implemented.
+-// Note that bcrelay v0.5 only relayed from LAN to VPN clients.
+-// It doesn't matter whether the systems on the VPN are on the LAN of the
+-// VPN server or have a VPN/PPTP connection (over the internet) to the VPN
+-// server. Broadcasts will always be relayed to/from all given interfaces. And
+-// as long as the subnet portion of the IP addresses of the systems on the VPN
+-// matches, the VPN server will be able to route properly. This means all
+-// networking applications/games that rely on a UDP broadcast from one or
+-// more PPP (VPN tunnel) interfaces will now see eachother and work over
+-// the VPN.
+-// Note that it depends on the networking application/game and whoever
+-// acts as application/game server/host who is sending (UPD) broadcasts
+-// and who is listening.
+-// 2) UDP broadcasts received on a PPP interface (VPN tunnel) sometimes
+-// don't carry the VPN IP address which pptpd provisioned. I've seen
+-// this happening on a WinXP SP1 box, especially when the application
+-// responsible for the UDP broadcasts isn't aware of the PPP interface.
+-// In this case it just uses the LAN IP src address for the IP src
+-// address of the inner (GRE encapsulated) IP packet. This breaks
+-// the "virtual LAN" and therefore bcrelay, as of this version, changes
+-// the src IP address to the VPN IP address (which pptpd provisioned)
++// Rewritten by Norbert van Bolhuis <norbert@vanbolhuis.demon.nl>
++// bcrelay (v1.0+) now supports/does:
++//
++// 1) Relaying from PPP (VPN tunnel) interfaces, hereby creating a
++// virtual LAN (w.r.t. UDP broadcasts) for VPN clients and ethernet
++// PCs belonging/matching the subnet portion of the VPN IP
++// addresses. So now broadcasting to/from all systems of the VPN
++// has been implemented. Note that bcrelay v0.5 only relayed from
++// LAN to VPN clients. It doesn't matter whether the systems on
++// the VPN are on the LAN of the VPN server or have a VPN/PPTP
++// connection (over the internet) to the VPN server. Broadcasts
++// will always be relayed to/from all given interfaces. And as long
++// as the subnet portion of the IP addresses of the systems on the
++// VPN matches, the VPN server will be able to route properly. This
++// means all networking applications/games that rely on a UDP
++// broadcast from one or more PPP (VPN tunnel) interfaces will now
++// see eachother and work over the VPN.
++//
++// Note that it depends on the networking application/game and
++// whoever acts as application/game server/host who is sending
++// (UDP) broadcasts and who is listening.
++//
++// 2) UDP broadcasts received on a PPP interface (VPN tunnel)
++// sometimes don't carry the VPN IP address which pptpd
++// provisioned. I've seen this happening on a WinXP SP1 box,
++// especially when the application responsible for the UDP
++// broadcasts isn't aware of the PPP interface. In this case it
++// just uses the LAN IP src address for the IP src address of the
++// inner (GRE encapsulated) IP packet. This breaks the "virtual
++// LAN" and therefore bcrelay, as of this version, changes the src
++// IP address to the VPN IP address (which pptpd provisioned)
+ // before relaying.
+-// 3) To avoid a UDP broadcast loop, bcrelay changes the IP TTL and the
+-// UDP checksum (to 1 and 0 respectively) of the UDP broadcasts it relays.
+-// No relaying will be done for UDP broadcasts with IP TTL=1 and UDP
+-// checksum=0. Could also (mis)use IP identification for this, but IP TTL
+-// and UDP chksum combination is expected to work fine.
+-// 4) bcrelay v0.5 forgot to update IP/UDP checksum when it changed the
+-// dest. IP address (e.g. from 192.168.1.255 to 255.255.255.255).
+-// Of course as of this version bcrelay always updates the IP/UDP
+-// checksum since the IP TTL and src IP address will change also.
+-// 5) Enhanced the (syslog) debugging capabilities. By default bcrelay will
+-// show what it is doing. Bcrelay will syslog the IP interfaces it tries
+-// to read/relay UDP broadcasts from/to. These interfaces are called
+-// the 'active interfaces', bcrelay will syslog the initial set of active
+-// interfaces and whenever the set changes. Currently there is no difference
+-// between an incoming interface (given with -i) and an outgoing interface
+-// (given with -o), so bcrelay won't show this attribute. Also, bcrelay will
+-// syslog a successfully relayed UDP broadcast, including the UDP port numbers,
+-// the incoming interface and the interface(s) to which it was successfully
+-// relayed. The (new) -n option allows to suppress syslog tracing.
+-// If -n is given, bcrelay shows/syslogs nothing, except fatal error
+-// messages.
++//
++// 3) To avoid a UDP broadcast loop, bcrelay changes the IP TTL and
++// the UDP checksum (to 1 and 0 respectively) of the UDP broadcasts
++// it relays. No relaying will be done for UDP broadcasts with IP
++// TTL=1 and UDP checksum=0. Could also (mis)use IP identification
++// for this, but IP TTL and UDP chksum combination is expected to
++// work fine.
++//
++// 4) bcrelay v0.5 forgot to update IP/UDP checksum when it changed
++// the dest. IP address (e.g. from 192.168.1.255 to
++// 255.255.255.255). Of course as of this version bcrelay always
++// updates the IP/UDP checksum since the IP TTL and src IP address
++// will change also.
++//
++// 5) Enhanced the (syslog) debugging capabilities. By default bcrelay
++// will show what it is doing. Bcrelay will syslog the IP
++// interfaces it tries to read/relay UDP broadcasts from/to. These
++// interfaces are called the 'active interfaces', bcrelay will
++// syslog the initial set of active interfaces and whenever the set
++// changes. Currently there is no difference between an incoming
++// interface (given with -i) and an outgoing interface (given with
++// -o), so bcrelay won't show this attribute. Also, bcrelay will
++// syslog a successfully relayed UDP broadcast, including the UDP
++// port numbers, the incoming interface and the interface(s) to
++// which it was successfully relayed. The (new) -n option allows to
++// suppress syslog tracing. If -n is given, bcrelay shows/syslogs
++// nothing, except fatal error messages.
+ //
+ // This software is completely free. You can use and/or modify this
+-// software to your hearts content. You are free to redistribute it as
+-// long as it is accompanied with the source and my credit is included.
++// software to your hearts content. You are free to redistribute it
++// as long as it is accompanied with the source and my credit is
++// included.
+
+ #ifdef HAVE_CONFIG_H
+ #include "config.h"
+@@ -126,14 +138,16 @@
+ #define IP_UDPPDU_CHECKSUM_MSB_PTR(udppdu) ((unsigned char *)(udppdu) + 6 )
+ #define IP_UDPPDU_CHECKSUM_LSB_PTR(udppdu) ((unsigned char *)(udppdu) + 7 )
+
+-#define MAXIF 255 // Maximum interfaces to use
+-#define MAX_SELECT_WAIT 3 // Maximum time (in secs) to wait for input on the socket/interfaces
+- // A time-out triggers the discovery of new interfaces.
+-#define MAX_NODISCOVER_IFS 12 // Maximum time (in secs) to elaps before a discovery of new
+- // interfaces is triggered. Only when a packet keeps coming in
+- // (this prevents a select time-out) a variable initialized with
+- // this #define becomes 0 and a rediscovery of the interfaces is
+- // triggered.
++// Maximum interfaces to use
++#define MAXIF 255
++// Maximum time (in secs) to wait for input on the socket/interfaces A
++// time-out triggers the discovery of new interfaces.
++#define MAX_SELECT_WAIT 3
++// Maximum time (in secs) to elapse before a discovery of new
++// interfaces is triggered. Only when a packet keeps coming in (this
++// prevents a select time-out) a variable initialized with this
++// #define becomes 0 and a rediscovery of the interfaces is triggered.
++#define MAX_NODISCOVER_IFS 12
+ #define MAX_IFLOGTOSTR 16
+
+ /* Local function prototypes */
+@@ -152,15 +166,13 @@ struct packet {
+
+
+ /*
+- * struct that keeps track of the interfaces of the system
+- * selected upon usage by bcrelay (with -i and -o option).
+- * An array of this struct is returned by discoverActiveInterfaces.
+- * This array is reset (filled from scratch) each time
+- * discoverActiveInterfaces is called.
++ * struct that keeps track of the interfaces of the system selected
++ * upon usage by bcrelay (with -i and -o option). An array of this
++ * struct is returned by discoverActiveInterfaces. This array is
++ * reset (filled from scratch) each time discoverActiveInterfaces is
++ * called.
+ */
+ struct iflist {
+-//Fix 3mar2003
+- //char index;
+ int index;
+ u_int32_t bcast;
+ char ifname[16+1];
+@@ -176,10 +188,10 @@ struct iflist {
+
+
+ /*
+- * struct that keeps track of the socket fd's for every interface
+- * that is in use (and thus present in iflist).
+- * Two permanent arrays of this struct are used, one for the
+- * previous/old list and one for the current list.
++ * struct that keeps track of the socket fd's for every interface that
++ * is in use (and thus present in iflist). Two permanent arrays of
++ * this struct are used, one for the previous/old list and one for the
++ * current list.
+ */
+ struct ifsnr {
+ int sock_nr;
+@@ -198,7 +210,7 @@ static void bind_to_iface(int fd, int if
+
+ /*
+ * This global variable determines whether NVBCR_PRINTF actually
+- * displays something. While developping v1.0, NVBCR_PRINTF were
++ * displays something. While developing v1.0, NVBCR_PRINTF were
+ * printf and a lot of tracing/logging/debugging was done with these.
+ * Of course, by default these 'info' messages have been turned off
+ * now. Enable by setting variable to 1. Note that output will only
+@@ -209,100 +221,100 @@ static int do_org_info_printfs = 0;
+ static int vnologging = 0;
+ static int vdaemon = 0;
+
+-#define NVBCR_PRINTF( args ) \
+- if ((vdaemon == 0) && (do_org_info_printfs == 1)) printf args
++#define NVBCR_PRINTF( args ) \
++ if ((vdaemon == 0) && (do_org_info_printfs == 1)) printf args
+
+ static char empty[1] = "";
+-static char interfaces[32];
++static char reg_interfaces[MAX_IFLOGTOSTR*2+2];
+ static char log_interfaces[MAX_IFLOGTOSTR*MAXIF];
+-static char log_relayed[(MAX_IFLOGTOSTR-1)*MAXIF+81];
++static char log_relayed[MAX_IFLOGTOSTR*MAXIF+81];
+ static char *ipsec = empty;
+
+ static void showusage(char *prog)
+ {
+- printf("\nBCrelay v%s\n\n", VERSION);
+- printf("A broadcast packet repeater. This packet repeater (currently designed for udp packets) will listen\n");
+- printf(" for broadcast packets. When it receives the packets, it will then re-broadcast the packet.\n\n");
+- printf("Usage: %s [options], where options are:\n\n", prog);
+- printf(" [-d] [--daemon] Run as daemon.\n");
+- printf(" [-h] [--help] Displays this help message.\n");
+- printf(" [-i] [--incoming <ifin>] Defines from which interface broadcasts will be relayed.\n");
+- printf(" [-n] [--nolog] No logging/tracing to /var/log/messages.\n");
+- printf(" [-o] [--outgoing <ifout>] Defines to which interface broadcasts will be relayed.\n");
+- printf(" [-s] [--ipsec <arg>] Defines an ipsec tunnel to be relayed to.\n");
+- printf(" Since ipsec tunnels terminate on the same interface, we need to define the broadcast\n");
+- printf(" address of the other end-point of the tunnel. This is done as ipsec0:x.x.x.255\n");
+- printf(" [-v] [--version] Displays the BCrelay version number.\n");
+- printf("\nLog messages and debugging go to syslog as DAEMON.\n\n");
+- printf("\nInterfaces can be specified as regexpressions, ie. ppp[0-9]+\n\n");
++ printf("\nBCrelay v%s\n\n", VERSION);
++ printf("A broadcast packet repeater. This packet repeater (currently designed for udp packets) will listen\n");
++ printf(" for broadcast packets. When it receives the packets, it will then re-broadcast the packet.\n\n");
++ printf("Usage: %s [options], where options are:\n\n", prog);
++ printf(" [-d] [--daemon] Run as daemon.\n");
++ printf(" [-h] [--help] Displays this help message.\n");
++ printf(" [-i] [--incoming <ifin>] Defines from which interface broadcasts will be relayed.\n");
++ printf(" [-n] [--nolog] No logging/tracing to /var/log/messages.\n");
++ printf(" [-o] [--outgoing <ifout>] Defines to which interface broadcasts will be relayed.\n");
++ printf(" [-s] [--ipsec <arg>] Defines an ipsec tunnel to be relayed to.\n");
++ printf(" Since ipsec tunnels terminate on the same interface, we need to define the broadcast\n");
++ printf(" address of the other end-point of the tunnel. This is done as ipsec0:x.x.x.255\n");
++ printf(" [-v] [--version] Displays the BCrelay version number.\n");
++ printf("\nLog messages and debugging go to syslog as DAEMON.\n\n");
++ printf("\nInterfaces can be specified as regexpressions, ie. ppp[0-9]+\n\n");
+ }
+
+ static void showversion()
+ {
+- printf("BCrelay v%s\n", VERSION);
++ printf("BCrelay v%s\n", VERSION);
+ }
+
+ #ifndef HAVE_DAEMON
+ static void my_daemon(int argc, char **argv)
+ {
+- pid_t pid;
++ pid_t pid;
+ #ifndef BCRELAY_BIN
+-/* Need a smart way to locate the binary -rdv */
++ /* Need a smart way to locate the binary -rdv */
+ #define BCRELAY_BIN argv[0]
+ #endif
+ #ifndef HAVE_FORK
+- /* need to use vfork - eg, uClinux */
+- char **new_argv;
+- extern char **environ;
+- int minusd=0;
+- int i;
+- int fdr;
+-
+- /* Strip -d option */
+- new_argv = malloc((argc) * sizeof(char **));
+- fdr = open("/dev/null", O_RDONLY);
+- new_argv[0] = BCRELAY_BIN;
+- for (i = 1; argv[i] != NULL; i++) {
+- if (fdr != 0) { dup2(fdr, 0); close(fdr); }
+- if ( (strcmp(argv[i],"-d")) == 0 ) {
+- minusd=1;
+- }
+- if (minusd) {
+- new_argv[i] = argv[i+1];
+- } else {
+- new_argv[i] = argv[i];
+- }
+- }
+- syslog(LOG_DEBUG, "Option parse OK, re-execing as daemon");
+- fflush(stderr);
+- if ((pid = vfork()) == 0) {
+- if (setsid() < 0) { /* shouldn't fail */
+- syslog(LOG_ERR, "Setsid failed!");
+- _exit(1);
+- }
+- chdir("/");
+- umask(0);
+- /* execve only returns on an error */
+- execve(BCRELAY_BIN, new_argv, environ);
+- exit(1);
+- } else if (pid > 0) {
+- syslog(LOG_DEBUG, "Success re-execing as daemon!");
+- exit(0);
+- } else {
+- syslog(LOG_ERR, "Error vforking");
+- exit(1);
+- }
+-#else
+- pid=fork();
+- if (pid<0) { syslog(LOG_ERR, "Error forking"); _exit(1); }
+- if (pid>0) { syslog(LOG_DEBUG, "Parent exits"); _exit(0); }
+- if (pid==0) { syslog(LOG_DEBUG, "Running as child"); }
+- /* child (daemon) continues */
++ /* need to use vfork - eg, uClinux */
++ char **new_argv;
++ extern char **environ;
++ int minusd=0;
++ int i;
++ int fdr;
++
++ /* Strip -d option */
++ new_argv = malloc((argc) * sizeof(char **));
++ fdr = open("/dev/null", O_RDONLY);
++ new_argv[0] = BCRELAY_BIN;
++ for (i = 1; argv[i] != NULL; i++) {
++ if (fdr != 0) { dup2(fdr, 0); close(fdr); }
++ if ( (strcmp(argv[i],"-d")) == 0 ) {
++ minusd=1;
++ }
++ if (minusd) {
++ new_argv[i] = argv[i+1];
++ } else {
++ new_argv[i] = argv[i];
++ }
++ }
++ syslog(LOG_DEBUG, "Option parse OK, re-execing as daemon");
++ fflush(stderr);
++ if ((pid = vfork()) == 0) {
+ if (setsid() < 0) { /* shouldn't fail */
+ syslog(LOG_ERR, "Setsid failed!");
+ _exit(1);
+ }
+ chdir("/");
++ umask(0);
++ /* execve only returns on an error */
++ execve(BCRELAY_BIN, new_argv, environ);
++ exit(1);
++ } else if (pid > 0) {
++ syslog(LOG_DEBUG, "Success re-execing as daemon!");
++ exit(0);
++ } else {
++ syslog(LOG_ERR, "Error vforking");
++ exit(1);
++ }
++#else
++ pid=fork();
++ if (pid<0) { syslog(LOG_ERR, "Error forking"); _exit(1); }
++ if (pid>0) { syslog(LOG_DEBUG, "Parent exits"); _exit(0); }
++ if (pid==0) { syslog(LOG_DEBUG, "Running as child"); }
++ /* child (daemon) continues */
++ if (setsid() < 0) { /* shouldn't fail */
++ syslog(LOG_ERR, "Setsid failed!");
++ _exit(1);
++ }
++ chdir("/");
+ #endif
+ }
+ #endif
+@@ -321,78 +333,81 @@ int main(int argc, char **argv) {
+ exit(1);
+ #endif
+
+- /* open a connection to the syslog daemon */
+- openlog("bcrelay", LOG_PID, PPTP_FACILITY);
++ /* open a connection to the syslog daemon */
++ openlog("bcrelay", LOG_PID, PPTP_FACILITY);
+
+ while (1) {
+- int option_index = 0;
++ int option_index = 0;
+
+- static struct option long_options[] =
+- {
+- {"nolog", 0, 0, 0},
+- {"daemon", 0, 0, 0},
+- {"help", 0, 0, 0},
+- {"incoming", 1, 0, 0},
+- {"outgoing", 1, 0, 0},
+- {"ipsec", 1, 0, 0},
+- {"version", 0, 0, 0},
+- {0, 0, 0, 0}
+- };
+-
+- c = getopt_long(argc, argv, "ndhi:o:s:v", long_options, &option_index);
+- if (c == -1)
+- break;
+- /* convert long options to short form */
+- if (c == 0)
+- c = "ndhiosv"[option_index];
+- switch (c) {
+- case 'n':
+- vnologging = 1;
+- break;
+- case 'd':
+- vdaemon = 1;
+- break;
+- case 'h':
+- showusage(argv[0]);
+- return 0;
+- case 'i':
+- ifin = strdup(optarg);
+- break;
+- case 'o':
+- ifout = strdup(optarg);
+- break;
+- case 's':
+- ipsec = strdup(optarg);
+- // Validate the ipsec parameters
+- regcomp(&preg, "ipsec[0-9]+:[0-9]+.[0-9]+.[0-9]+.255", REG_EXTENDED);
+- if (regexec(&preg, ipsec, 0, NULL, 0)) {
+- syslog(LOG_INFO,"Bad syntax: %s", ipsec);
+- fprintf(stderr, "\nBad syntax: %s\n", ipsec);
+- showusage(argv[0]);
+- return 0;
+- } else {
+- regfree(&preg);
+- break;
+- }
+- case 'v':
+- showversion();
+- return 0;
+- default:
+- showusage(argv[0]);
+- return 1;
+- }
++ static struct option long_options[] =
++ {
++ {"nolog", 0, 0, 0},
++ {"daemon", 0, 0, 0},
++ {"help", 0, 0, 0},
++ {"incoming", 1, 0, 0},
++ {"outgoing", 1, 0, 0},
++ {"ipsec", 1, 0, 0},
++ {"version", 0, 0, 0},
++ {0, 0, 0, 0}
++ };
++
++ c = getopt_long(argc, argv, "ndhi:o:s:v", long_options, &option_index);
++ if (c == -1)
++ break;
++ /* convert long options to short form */
++ if (c == 0)
++ c = "ndhiosv"[option_index];
++ switch (c) {
++ case 'n':
++ vnologging = 1;
++ break;
++ case 'd':
++ vdaemon = 1;
++ break;
++ case 'h':
++ showusage(argv[0]);
++ return 0;
++ case 'i':
++ ifin = strdup(optarg);
++ break;
++ case 'o':
++ ifout = strdup(optarg);
++ break;
++ case 's':
++ ipsec = strdup(optarg);
++ // Validate the ipsec parameters
++ regcomp(&preg, "ipsec[0-9]+:[0-9]+.[0-9]+.[0-9]+.255", REG_EXTENDED);
++ if (regexec(&preg, ipsec, 0, NULL, 0)) {
++ syslog(LOG_INFO,"Bad syntax: %s", ipsec);
++ fprintf(stderr, "\nBad syntax: %s\n", ipsec);
++ showusage(argv[0]);
++ return 0;
++ } else {
++ regfree(&preg);
++ break;
++ }
++ case 'v':
++ showversion();
++ return 0;
++ default:
++ showusage(argv[0]);
++ return 1;
++ }
+ }
+ if (ifin == empty) {
+- syslog(LOG_INFO,"Incoming interface required!");
+- showusage(argv[0]);
+- _exit(1);
++ syslog(LOG_INFO,"Incoming interface required!");
++ showusage(argv[0]);
++ _exit(1);
+ }
+ if (ifout == empty && ipsec == empty) {
+- syslog(LOG_INFO,"Listen-mode or outgoing or IPsec interface required!");
+- showusage(argv[0]);
+- _exit(1);
+- } else {
+- sprintf(interfaces,"%s|%s", ifin, ifout);
++ syslog(LOG_INFO,"Listen-mode or outgoing or IPsec interface required!");
++ showusage(argv[0]);
++ _exit(1);
++ }
++ if (snprintf(reg_interfaces, sizeof(reg_interfaces),
++ "%s|%s", ifin, ifout) >= sizeof(reg_interfaces)) {
++ syslog(LOG_ERR, "interface names exceed size");
++ _exit(1);
+ }
+
+ // If specified, become Daemon.
+@@ -426,7 +441,6 @@ static void mainloop(int argc, char **ar
+ {
+ socklen_t salen = sizeof(struct sockaddr_ll);
+ int i, s, rcg, j, no_discifs_cntr, ifs_change;
+- int logstr_cntr;
+ struct iflist *iflist = NULL; // Initialised after the 1st packet
+ struct sockaddr_ll sa;
+ struct packet *ipp_p;
+@@ -436,7 +450,10 @@ static void mainloop(int argc, char **ar
+ static struct ifsnr old_ifsnr[MAXIF+1]; // Old iflist to socket fd's mapping list
+ static struct ifsnr cur_ifsnr[MAXIF+1]; // Current iflist to socket fd's mapping list
+ unsigned char buf[1518];
+- char *logstr = empty;
++
++ char *lptr; /* log buffer pointer for next chunk append */
++ int lsize = 0; /* count of remaining unused bytes in log buffer */
++ int chunk; /* bytes to be added to log buffer by chunk */
+
+ no_discifs_cntr = MAX_NODISCOVER_IFS;
+ ifs_change = 0;
+@@ -449,7 +466,8 @@ static void mainloop(int argc, char **ar
+
+
+ /*
+- * Discover interfaces (initial set) and create a dedicated socket bound to the interface
++ * Discover interfaces (initial set) and create a dedicated socket
++ * bound to the interface
+ */
+ memset(old_ifsnr, -1, sizeof(old_ifsnr));
+ memset(cur_ifsnr, -1, sizeof(cur_ifsnr));
+@@ -464,313 +482,367 @@ static void mainloop(int argc, char **ar
+ }
+ NVBCR_PRINTF(("Displaying INITIAL active interfaces..\n"));
+ if (vnologging == 0) {
+- logstr = log_interfaces;
+- logstr_cntr = sprintf(logstr, "Initial active interfaces: ");
+- logstr += logstr_cntr;
++ lptr = log_interfaces;
++ lsize = sizeof(log_interfaces);
++ chunk = snprintf(lptr, lsize, "%s ", "Initial active interfaces:");
++ if (chunk < lsize) {
++ lptr += chunk;
++ lsize -= chunk;
++ }
+ }
+ for (i = 0; iflist[i].index; i++)
+- {
+- NVBCR_PRINTF(("\t\tactive interface number: %d, if=(%s), sock_nr=%d\n", i, iflistToString(&(iflist[i])), cur_ifsnr[i].sock_nr));
+- if (vnologging == 0) {
+- logstr_cntr = sprintf(logstr, "%s ", iflistLogIToString(&(iflist[i]), i, &(cur_ifsnr[i])));
+- logstr += logstr_cntr;
++ {
++ NVBCR_PRINTF(("\t\tactive interface number: %d, if=(%s), sock_nr=%d\n", i, iflistToString(&(iflist[i])), cur_ifsnr[i].sock_nr));
++ if (vnologging == 0) {
++ chunk = snprintf(lptr, lsize, "%s ",
++ iflistLogIToString(&(iflist[i]), i, &(cur_ifsnr[i])));
++ if (chunk < lsize) {
++ lptr += chunk;
++ lsize -= chunk;
++ }
++ }
+ }
+- }
+ if (vnologging == 0) syslog(LOG_INFO, "%s", log_interfaces);
+
+ // Main loop
+ while (1)
+- {
+-
+- /*
+- * Check all (interface) sockets for incoming packets
+- */
+- FD_ZERO(&sock_set);
+- for (i=0; iflist[i].index; ++i)
+- {
+- if (cur_ifsnr[i].sock_nr >= 0) {
+- FD_SET(cur_ifsnr[i].sock_nr, &sock_set);
+- }
+- }
+-
+- /*
+- * Don't wait more than MAX_SELECT_WAIT seconds
+- */
+- time_2_wait.tv_sec = MAX_SELECT_WAIT;
+- time_2_wait.tv_usec = 0L;
+-
+- /* select on sockets */
+- rcg = select(MAXIF, &sock_set, (fd_set *) NULL,(fd_set *) NULL, &time_2_wait);
+-
+- if (rcg < 0)
+ {
+- syslog(LOG_ERR, "Error, select error! (rv=%d, errno=%d)", rcg, errno);
+- exit(1);
+- }
+
+- if (rcg == 0)
+- {
+- /* TimeOut, rediscover interfaces */
+- NVBCR_PRINTF(("Select timeout, rediscover interfaces\n"));
+- copy_ifsnr(cur_ifsnr, old_ifsnr);
+- memset(cur_ifsnr, -1, sizeof(cur_ifsnr));
+- iflist = discoverActiveInterfaces(s);
+ /*
+- * Build new cur_ifsnr list.
+- * Make iflist[i] correspond with cur_ifsnr[i], so iflist[i].index == cur_ifsnr[i].ifindex
+- * The old list (old_ifsnr) is used to compare.
++ * Check all (interface) sockets for incoming packets
+ */
+- for (i=0; iflist[i].index; ++i) {
+- /* check to see if it is a NEW interface */
+- int fsnr = find_sock_nr(old_ifsnr, iflist[i].index);
+- if (fsnr == -1) {
+- /* found new interface, open dedicated socket and bind it to the interface */
+- if ((cur_ifsnr[i].sock_nr = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL))) < 0) {
+- syslog(LOG_ERR, "mainloop: Error, socket error! (rv=%d, errno=%d)", cur_ifsnr[i].sock_nr, errno);
+- exit(1);
+- }
+- bind_to_iface(cur_ifsnr[i].sock_nr, iflist[i].index);
+- ifs_change = 1;
+- }
+- else
++ FD_ZERO(&sock_set);
++ for (i=0; iflist[i].index; ++i)
+ {
+- /*
+- * not a new interface, socket already openen, interface already
+- * bound. Update cur_ifsnr.
+- */
+- cur_ifsnr[i].sock_nr = fsnr;
+- }
+- cur_ifsnr[i].ifindex = iflist[i].index;
+- }
+- /* Close disappeared interfaces */
+- for (i=0; i<MAXIF; ++i)
+- {
+- if ((old_ifsnr[i].sock_nr != -1) && (old_ifsnr[i].ifindex != -1) &&
+- (find_sock_nr(cur_ifsnr, old_ifsnr[i].ifindex) == -1)) {
+- NVBCR_PRINTF(("Closing an interface (it disappeared), namely: (s_nr=%d, ifidx=%d)\n", old_ifsnr[i].sock_nr, old_ifsnr[i].ifindex));
+- close(old_ifsnr[i].sock_nr);
+- old_ifsnr[i].sock_nr = -1;
+- old_ifsnr[i].ifindex = -1;
+- ifs_change = 1;
+- }
+- }
+- if (ifs_change == 1)
+- {
+- NVBCR_PRINTF(("Active interface set changed --> displaying current active interfaces..\n"));
+- if (vnologging == 0) {
+- logstr = log_interfaces;
+- logstr_cntr = sprintf(logstr, "Active interface set changed to: ");
+- logstr += logstr_cntr;
+- }
+- for (i = 0; iflist[i].index; i++)
+- {
+- NVBCR_PRINTF(("\t\tactive interface number: %d, if=(%s), sock_nr=%d\n", i, iflistToString(&(iflist[i])), cur_ifsnr[i].sock_nr));
+- if (vnologging == 0) {
+- logstr_cntr = sprintf(logstr, "%s ", iflistLogIToString(&(iflist[i]), i, &(cur_ifsnr[i])));
+- logstr += logstr_cntr;
++ if (cur_ifsnr[i].sock_nr >= 0) {
++ FD_SET(cur_ifsnr[i].sock_nr, &sock_set);
+ }
+ }
+- if (vnologging == 0) syslog(LOG_INFO, "%s", log_interfaces);
+- ifs_change = 0;
+- }
+- continue;
+- }
+
+- if (rcg > 0)
+- {
+- /* rcg interfaces have pending input */
+- for (i=0; ((iflist[i].index != 0) && (rcg > 0)); ++i)
+- {
+- if ((cur_ifsnr[i].sock_nr != -1) && (FD_ISSET(cur_ifsnr[i].sock_nr,&sock_set)))
+- {
+- /* Valid socket number and pending input, let's read */
+- int rlen = read(cur_ifsnr[i].sock_nr, buf, sizeof(buf));
+- ipp_p = (struct packet *)&(buf[0]);
+- NVBCR_PRINTF(("IP_Packet=(tot_len=%d, id=%02x%02x, ttl=%d, prot=%s, src_ip=%d.%d.%d.%d, dst_ip=%d.%d.%d.%d) (on if: %d/%d) ", ntohs(ipp_p->ip.tot_len), (ntohs(ipp_p->ip.id))>>8, (ntohs(ipp_p->ip.id))&0x00ff, ipp_p->ip.ttl, IpProtToString(ipp_p->ip.protocol), (ntohl(ipp_p->ip.saddr))>>24, ((ntohl(ipp_p->ip.saddr))&0x00ff0000)>>16, ((ntohl(ipp_p->ip.saddr))&0x0000ff00)>>8, (ntohl(ipp_p->ip.saddr))&0x000000ff, (ntohl(ipp_p->ip.daddr))>>24, ((ntohl(ipp_p->ip.daddr))&0x00ff0000)>>16, ((ntohl(ipp_p->ip.daddr))&0x0000ff00)>>8, (ntohl(ipp_p->ip.daddr))&0x000000ff, i, iflist[i].index));
+- rcg -= 1;
+-
+- if ( (ipp_p->ip.protocol == IPPROTO_UDP) &&
+- (((ntohl(ipp_p->ip.daddr)) & 0x000000ff) == 0x000000ff) &&
+- (ipp_p->ip.ttl != 1) &&
+- (!((*IP_UDPPDU_CHECKSUM_MSB_PTR((unsigned char *)ipp_p+(4*ipp_p->ip.ihl)) == 0) &&
+- (*IP_UDPPDU_CHECKSUM_LSB_PTR((unsigned char *)ipp_p+(4*ipp_p->ip.ihl)) == 0))) )
+- {
+- int nrsent;
+- int ifindex_to_exclude = iflist[i].index;
++ /*
++ * Don't wait more than MAX_SELECT_WAIT seconds
++ */
++ time_2_wait.tv_sec = MAX_SELECT_WAIT;
++ time_2_wait.tv_usec = 0L;
+
+- NVBCR_PRINTF(("is an UDP BROADCAST (dstPort=%d, srcPort=%d) (with TTL!=1 and UDP_CHKSUM!=0)\n\n",
+- ntohs(ipp_p->udp.dest), ntohs(ipp_p->udp.source)));
+- if (vnologging == 0) {
+- logstr = log_relayed;
+- logstr_cntr = sprintf(logstr, "UDP_BroadCast(sp=%d,dp=%d) from: %s relayed to: ", ntohs(ipp_p->udp.source),
+- ntohs(ipp_p->udp.dest), iflistLogRToString(&(iflist[i]), i, &(cur_ifsnr[i])));
+- logstr += logstr_cntr;
+- }
++ /* select on sockets */
++ rcg = select(MAXIF, &sock_set, (fd_set *) NULL,(fd_set *) NULL, &time_2_wait);
+
+- /* going to relay a broadcast packet on all the other interfaces */
+- for (j=0; iflist[j].index; ++j)
+- {
+- int prepare_ipp = 0; // Changing the incoming UDP broadcast needs to be done once
++ if (rcg < 0)
++ {
++ syslog(LOG_ERR, "Error, select error! (rv=%d, errno=%d)", rcg, errno);
++ exit(1);
++ }
+
+- if (iflist[j].index != ifindex_to_exclude)
++ if (rcg == 0)
++ {
++ /* TimeOut, rediscover interfaces */
++ NVBCR_PRINTF(("Select timeout, rediscover interfaces\n"));
++ copy_ifsnr(cur_ifsnr, old_ifsnr);
++ memset(cur_ifsnr, -1, sizeof(cur_ifsnr));
++ iflist = discoverActiveInterfaces(s);
++ /*
++ * Build new cur_ifsnr list. Make iflist[i] correspond with
++ * cur_ifsnr[i], so iflist[i].index == cur_ifsnr[i].ifindex
++ * The old list (old_ifsnr) is used to compare.
++ */
++ for (i=0; iflist[i].index; ++i) {
++ /* check to see if it is a NEW interface */
++ int fsnr = find_sock_nr(old_ifsnr, iflist[i].index);
++ if (fsnr == -1) {
++ /* found new interface, open dedicated socket and bind
++ it to the interface */
++ if ((cur_ifsnr[i].sock_nr = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL))) < 0) {
++ syslog(LOG_ERR, "mainloop: Error, socket error! (rv=%d, errno=%d)", cur_ifsnr[i].sock_nr, errno);
++ exit(1);
++ }
++ bind_to_iface(cur_ifsnr[i].sock_nr, iflist[i].index);
++ ifs_change = 1;
++ }
++ else
+ {
+- NVBCR_PRINTF(("Going to sent UDP Broadcast on interface: %s, sock_nr=%d\n", iflistToString(&(iflist[j])), cur_ifsnr[j].sock_nr));
+-
+- memset(&sa, 0, salen);
+-
+- sa.sll_family = AF_PACKET;
+- sa.sll_ifindex = iflist[j].index; /* Must be the SIOCGIFINDEX number */
+- // Set the outgoing hardware address to 1's. True Broadcast
+- sa.sll_addr[0] = sa.sll_addr[1] = sa.sll_addr[2] = sa.sll_addr[3] = 0xff;
+- sa.sll_addr[4] = sa.sll_addr[5] = sa.sll_addr[6] = sa.sll_addr[7] = 0xff;
+- sa.sll_halen = 6;
+-
+ /*
+- * htons(ETH_P_IP) is necessary otherwise sendto will
+- * succeed but no packet is actually sent on the wire (this
+- * was the case for PPP interfaces, for ETH interfaces an unknown
+- * LAN frame is sent if htons(ETH_P_IP) is not set as protocol).
++ * not a new interface, socket already openen,
++ * interface already bound. Update cur_ifsnr.
+ */
+- sa.sll_protocol = htons(ETH_P_IP); /* ETH_P_PPP_MP */
++ cur_ifsnr[i].sock_nr = fsnr;
++ }
++ cur_ifsnr[i].ifindex = iflist[i].index;
++ }
++ /* Close disappeared interfaces */
++ for (i=0; i<MAXIF; ++i)
++ {
++ if ((old_ifsnr[i].sock_nr != -1) && (old_ifsnr[i].ifindex != -1) &&
++ (find_sock_nr(cur_ifsnr, old_ifsnr[i].ifindex) == -1)) {
++ NVBCR_PRINTF(("Closing an interface (it disappeared), namely: (s_nr=%d, ifidx=%d)\n", old_ifsnr[i].sock_nr, old_ifsnr[i].ifindex));
++ close(old_ifsnr[i].sock_nr);
++ old_ifsnr[i].sock_nr = -1;
++ old_ifsnr[i].ifindex = -1;
++ ifs_change = 1;
++ }
++ }
++ if (ifs_change == 1)
++ {
++ NVBCR_PRINTF(("Active interface set changed --> displaying current active interfaces..\n"));
++ if (vnologging == 0) {
++ lptr = log_interfaces;
++ lsize = sizeof(log_interfaces);
++ chunk = snprintf(lptr, lsize, "%s ",
++ "Active interface set changed to:");
++ if (chunk < lsize) {
++ lptr += chunk;
++ lsize -= chunk;
++ }
++ }
++ for (i = 0; iflist[i].index; i++)
++ {
++ NVBCR_PRINTF(("\t\tactive interface number: %d, if=(%s), sock_nr=%d\n", i, iflistToString(&(iflist[i])), cur_ifsnr[i].sock_nr));
++ if (vnologging == 0) {
++ chunk = snprintf(lptr, lsize, "%s ",
++ iflistLogIToString(&(iflist[i]), i, &(cur_ifsnr[i])));
++ if (chunk < lsize) {
++ lptr += chunk;
++ lsize -= chunk;
++ }
++ }
++ }
++ if (vnologging == 0) syslog(LOG_INFO, "%s", log_interfaces);
++ ifs_change = 0;
++ }
++ continue;
++ }
++
++ if (rcg > 0)
++ {
++ /* rcg interfaces have pending input */
++ for (i=0; ((iflist[i].index != 0) && (rcg > 0)); ++i)
++ {
++ if ((cur_ifsnr[i].sock_nr != -1) && (FD_ISSET(cur_ifsnr[i].sock_nr,&sock_set)))
++ {
++ /* Valid socket number and pending input, let's read */
++ int rlen = read(cur_ifsnr[i].sock_nr, buf, sizeof(buf));
++ ipp_p = (struct packet *)&(buf[0]);
++ NVBCR_PRINTF(("IP_Packet=(tot_len=%d, id=%02x%02x, ttl=%d, prot=%s, src_ip=%d.%d.%d.%d, dst_ip=%d.%d.%d.%d) (on if: %d/%d) ", ntohs(ipp_p->ip.tot_len), (ntohs(ipp_p->ip.id))>>8, (ntohs(ipp_p->ip.id))&0x00ff, ipp_p->ip.ttl, IpProtToString(ipp_p->ip.protocol), (ntohl(ipp_p->ip.saddr))>>24, ((ntohl(ipp_p->ip.saddr))&0x00ff0000)>>16, ((ntohl(ipp_p->ip.saddr))&0x0000ff00)>>8, (ntohl(ipp_p->ip.saddr))&0x000000ff, (ntohl(ipp_p->ip.daddr))>>24, ((ntohl(ipp_p->ip.daddr))&0x00ff0000)>>16, ((ntohl(ipp_p->ip.daddr))&0x0000ff00)>>8, (ntohl(ipp_p->ip.daddr))&0x000000ff, i, iflist[i].index));
++ rcg -= 1;
++
++ if ( (ipp_p->ip.protocol == IPPROTO_UDP) &&
++ (((ntohl(ipp_p->ip.daddr)) & 0x000000ff) == 0x000000ff) &&
++ (ipp_p->ip.ttl != 1) &&
++ (!((*IP_UDPPDU_CHECKSUM_MSB_PTR((unsigned char *)ipp_p+(4*ipp_p->ip.ihl)) == 0) &&
++ (*IP_UDPPDU_CHECKSUM_LSB_PTR((unsigned char *)ipp_p+(4*ipp_p->ip.ihl)) == 0))) )
++ {
++ int nrsent;
++ int ifindex_to_exclude = iflist[i].index;
++
++ NVBCR_PRINTF(("is an UDP BROADCAST (dstPort=%d, srcPort=%d) (with TTL!=1 and UDP_CHKSUM!=0)\n\n",
++ ntohs(ipp_p->udp.dest), ntohs(ipp_p->udp.source)));
++ if (vnologging == 0) {
++ lptr = log_relayed;
++ lsize = sizeof(log_relayed);
++ chunk = snprintf(lptr, lsize,
++ "UDP_BroadCast(sp=%d,dp=%d) from: %s relayed to: ",
++ ntohs(ipp_p->udp.source),
++ ntohs(ipp_p->udp.dest),
++ iflistLogRToString(&(iflist[i]), i, &(cur_ifsnr[i])));
++ if (chunk < lsize) {
++ lptr += chunk;
++ lsize -= chunk;
++ }
++ }
+
+- if (prepare_ipp == 0) {
+- // change TimeToLive to 1, This is to avoid loops, bcrelay will *NOT* relay
+- // anything with TTL==1.
+- ipp_p->ip.ttl = 1;
++ /* going to relay a broadcast packet on all the
++ other interfaces */
++ for (j=0; iflist[j].index; ++j)
++ {
++ int prepare_ipp = 0; // Changing the incoming UDP broadcast needs to be done once
++
++ if (iflist[j].index != ifindex_to_exclude)
++ {
++ NVBCR_PRINTF(("Going to sent UDP Broadcast on interface: %s, sock_nr=%d\n", iflistToString(&(iflist[j])), cur_ifsnr[j].sock_nr));
++
++ memset(&sa, 0, salen);
++
++ sa.sll_family = AF_PACKET;
++ sa.sll_ifindex = iflist[j].index; /* Must be the SIOCGIFINDEX number */
++ // Set the outgoing hardware address to 1's. True Broadcast
++ sa.sll_addr[0] = sa.sll_addr[1] = sa.sll_addr[2] = sa.sll_addr[3] = 0xff;
++ sa.sll_addr[4] = sa.sll_addr[5] = sa.sll_addr[6] = sa.sll_addr[7] = 0xff;
++ sa.sll_halen = 6;
++
++ /*
++ * htons(ETH_P_IP) is necessary
++ * otherwise sendto will succeed but no
++ * packet is actually sent on the wire
++ * (this was the case for PPP
++ * interfaces, for ETH interfaces an
++ * unknown LAN frame is sent if
++ * htons(ETH_P_IP) is not set as
++ * protocol).
++ */
++ sa.sll_protocol = htons(ETH_P_IP); /* ETH_P_PPP_MP */
++
++ if (prepare_ipp == 0) {
++ // change TimeToLive to 1, This is to
++ // avoid loops, bcrelay will *NOT*
++ // relay anything with TTL==1.
++ ipp_p->ip.ttl = 1;
+
+- // The CRC gets broken here when sending over ipsec tunnels but that
+- // should not matter as we reassemble the packet at the other end.
+- ipp_p->ip.daddr = iflist[j].bcast;
++ // The CRC gets broken here when
++ // sending over ipsec tunnels but that
++ // should not matter as we reassemble
++ // the packet at the other end.
++ ipp_p->ip.daddr = iflist[j].bcast;
+
+- // check IP srcAddr (on some winXP boxes it is found to be
+- // different from the configured ppp address).
+- // Only do this for PPP interfaces.
+- if ((iflist[i].flags1 & IFLIST_FLAGS1_IF_IS_PPP) &&
+- (ntohl(ipp_p->ip.saddr) != iflist[i].ifdstaddr))
+- {
+- ipp_p->ip.saddr = htonl(iflist[i].ifdstaddr);
+- iflist[i].flags1 |= IFLIST_FLAGS1_CHANGED_INNER_SADDR;
+- }
++ // check IP srcAddr (on some winXP
++ // boxes it is found to be different
++ // from the configured ppp address).
++ // Only do this for PPP interfaces.
++ if ((iflist[i].flags1 & IFLIST_FLAGS1_IF_IS_PPP) &&
++ (ntohl(ipp_p->ip.saddr) != iflist[i].ifdstaddr))
++ {
++ ipp_p->ip.saddr = htonl(iflist[i].ifdstaddr);
++ iflist[i].flags1 |= IFLIST_FLAGS1_CHANGED_INNER_SADDR;
++ }
+
+- // Update IP checkSum (TTL and src/dest IP Address might have changed)
+- ip_update_checksum((unsigned char *)ipp_p);
+- /* Disable upper layer checksum */
+- udppdu = (unsigned char *)ipp_p + (4 * ipp_p->ip.ihl);
+- *IP_UDPPDU_CHECKSUM_MSB_PTR(udppdu) = (unsigned char)0;
+- *IP_UDPPDU_CHECKSUM_LSB_PTR(udppdu) = (unsigned char)0;
+-
+- prepare_ipp = 1;
++ // Update IP checkSum (TTL and
++ // src/dest IP Address might have
++ // changed)
++ ip_update_checksum((unsigned char *)ipp_p);
++ /* Disable upper layer checksum */
++ udppdu = (unsigned char *)ipp_p + (4 * ipp_p->ip.ihl);
++ *IP_UDPPDU_CHECKSUM_MSB_PTR(udppdu) = (unsigned char)0;
++ *IP_UDPPDU_CHECKSUM_LSB_PTR(udppdu) = (unsigned char)0;
++
++ prepare_ipp = 1;
++ }
++
++ /*
++ * The beauty of sending IP packets on a
++ * PACKET socket of type SOCK_DGRAM is
++ * that there is no need to concern
++ * about the physical/link layer header
++ * because it is filled in automatically
++ * (based on the contents of sa).
++ */
++ if ((nrsent = sendto(cur_ifsnr[j].sock_nr, ipp_p, rlen, MSG_DONTWAIT|MSG_TRYHARD, (struct sockaddr *)&sa, salen)) < 0)
++ {
++ if (errno == ENETDOWN) {
++ syslog(LOG_NOTICE, "ignored ENETDOWN from sendto(), a network interface was going down?");
++ } else if (errno == ENXIO) {
++ syslog(LOG_NOTICE, "ignored ENXIO from sendto(), a network interface went down?");
++ } else if (errno == ENOBUFS) {
++ syslog(LOG_NOTICE, "ignored ENOBUFS from sendto(), temporary shortage of buffer memory");
++ } else {
++ syslog(LOG_ERR, "mainloop: Error, sendto failed! (rv=%d, errno=%d)", nrsent, errno);
++ exit(1);
++ }
++ }
++ NVBCR_PRINTF(("Successfully relayed %d bytes \n", nrsent));
++ if (vnologging == 0) {
++ chunk = snprintf(lptr, lsize, "%s ",
++ iflistLogRToString(&(iflist[j]), j, &(cur_ifsnr[j])));
++ if (chunk < lsize) {
++ lptr += chunk;
++ lsize -= chunk;
++ }
++ }
++ }
++ }
++ if (vnologging == 0) syslog(LOG_INFO, "%s", log_relayed);
++ } else {
++ NVBCR_PRINTF(("is NOT an UDP BROADCAST (with TTL!=1 and UDP_CHKSUM!=0)\n\n"));
++ }
+ }
++ }
++ /*
++ * Don't forget to discover new interfaces if we keep
++ * getting incoming packets (on an already discovered
++ * interface).
++ */
++ if (no_discifs_cntr == 0)
++ {
++ no_discifs_cntr = MAX_NODISCOVER_IFS;
+
+- /*
+- * The beauty of sending IP packets on a PACKET socket of type SOCK_DGRAM is that
+- * there is no need to concern about the physical/link layer header because it is
+- * filled in automatically (based on the contents of sa).
+- */
+- if ((nrsent = sendto(cur_ifsnr[j].sock_nr, ipp_p, rlen, MSG_DONTWAIT|MSG_TRYHARD, (struct sockaddr *)&sa, salen)) < 0)
+- {
+- if (errno == ENETDOWN) {
+- syslog(LOG_NOTICE, "ignored ENETDOWN from sendto(), a network interface was going down?");
+- } else if (errno == ENXIO) {
+- syslog(LOG_NOTICE, "ignored ENXIO from sendto(), a network interface went down?");
+- } else if (errno == ENOBUFS) {
+- syslog(LOG_NOTICE, "ignored ENOBUFS from sendto(), temporary shortage of buffer memory");
+- } else {
+- syslog(LOG_ERR, "mainloop: Error, sendto failed! (rv=%d, errno=%d)", nrsent, errno);
++ /* no_discifs_cntr became 0, rediscover interfaces */
++ NVBCR_PRINTF(("no_discifs_cntr became 0, rediscover interfaces\n"));
++ copy_ifsnr(cur_ifsnr, old_ifsnr);
++ memset(cur_ifsnr, -1, sizeof(cur_ifsnr));
++ iflist = discoverActiveInterfaces(s);
++ /*
++ * Build new cur_ifsnr list.
++ * Make iflist[i] correspond with cur_ifsnr[i], so iflist[i].index == cur_ifsnr[i].ifindex
++ * The old list (old_ifsnr) is used to compare.
++ */
++ for (i=0; iflist[i].index; ++i) {
++ /* check to see if it is a NEW interface */
++ int fsnr = find_sock_nr(old_ifsnr, iflist[i].index);
++ if (fsnr == -1) {
++ /* found new interface, open dedicated socket and
++ bind it to the interface */
++ if ((cur_ifsnr[i].sock_nr = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL))) < 0) {
++ syslog(LOG_ERR, "mainloop: Error, socket error! (rv=%d, errno=%d)", cur_ifsnr[i].sock_nr, errno);
+ exit(1);
+ }
++ bind_to_iface(cur_ifsnr[i].sock_nr, iflist[i].index);
++ ifs_change = 1;
+ }
+- NVBCR_PRINTF(("Successfully relayed %d bytes \n", nrsent));
+- if (vnologging == 0) {
+- logstr_cntr = sprintf(logstr, "%s ", iflistLogRToString(&(iflist[j]), j, &(cur_ifsnr[j])));
+- logstr += logstr_cntr;
+- }
++ else
++ {
++ /*
++ * not a new interface, socket already opened,
++ * interface already bound. Update cur_ifsnr.
++ */
++ cur_ifsnr[i].sock_nr = fsnr;
++ }
++ cur_ifsnr[i].ifindex = iflist[i].index;
+ }
++ /* Close disappeared interfaces */
++ for (i=0; i<MAXIF; ++i)
++ {
++ if ((old_ifsnr[i].sock_nr != -1) && (old_ifsnr[i].ifindex != -1) &&
++ (find_sock_nr(cur_ifsnr, old_ifsnr[i].ifindex) == -1)) {
++ NVBCR_PRINTF(("Closing an interface (it disappeared), namely: (s_nr=%d, ifidx=%d)\n", old_ifsnr[i].sock_nr, old_ifsnr[i].ifindex));
++ close(old_ifsnr[i].sock_nr);
++ old_ifsnr[i].sock_nr = -1;
++ old_ifsnr[i].ifindex = -1;
++ ifs_change = 1;
++ }
++ }
++ if (ifs_change == 1)
++ {
++ NVBCR_PRINTF(("Active interface set changed --> displaying current active interfaces..\n"));
++ if (vnologging == 0) {
++ lptr = log_interfaces;
++ lsize = sizeof(log_interfaces);
++ chunk = snprintf(lptr, lsize, "%s ",
++ "Active interface set changed to:");
++ if (chunk < lsize) {
++ lptr += chunk;
++ lsize -= chunk;
++ }
++ }
++ for (i = 0; iflist[i].index; i++)
++ {
++ NVBCR_PRINTF(("\t\tactive interface number: %d, if=(%s), sock_nr=%d\n", i, iflistToString(&(iflist[i])), cur_ifsnr[i].sock_nr));
++ if (vnologging == 0) {
++ chunk = snprintf(lptr, lsize, "%s ",
++ iflistLogIToString(&(iflist[i]), i, &(cur_ifsnr[i])));
++ if (chunk < lsize) {
++ lptr += chunk;
++ lsize -= chunk;
++ }
++ }
++ }
++ if (vnologging == 0) syslog(LOG_INFO, "%s", log_interfaces);
++ ifs_change = 0;
++ }
+ }
+- if (vnologging == 0) syslog(LOG_INFO, "%s", log_relayed);
+- } else {
+- NVBCR_PRINTF(("is NOT an UDP BROADCAST (with TTL!=1 and UDP_CHKSUM!=0)\n\n"));
+- }
+- }
+- }
+- /*
+- * Don't forget to discover new interfaces if we keep getting
+- * incoming packets (on an already discovered interface).
+- */
+- if (no_discifs_cntr == 0)
+- {
+- no_discifs_cntr = MAX_NODISCOVER_IFS;
+-
+- /* no_discifs_cntr became 0, rediscover interfaces */
+- NVBCR_PRINTF(("no_discifs_cntr became 0, rediscover interfaces\n"));
+- copy_ifsnr(cur_ifsnr, old_ifsnr);
+- memset(cur_ifsnr, -1, sizeof(cur_ifsnr));
+- iflist = discoverActiveInterfaces(s);
+- /*
+- * Build new cur_ifsnr list.
+- * Make iflist[i] correspond with cur_ifsnr[i], so iflist[i].index == cur_ifsnr[i].ifindex
+- * The old list (old_ifsnr) is used to compare.
+- */
+- for (i=0; iflist[i].index; ++i) {
+- /* check to see if it is a NEW interface */
+- int fsnr = find_sock_nr(old_ifsnr, iflist[i].index);
+- if (fsnr == -1) {
+- /* found new interface, open dedicated socket and bind it to the interface */
+- if ((cur_ifsnr[i].sock_nr = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL))) < 0) {
+- syslog(LOG_ERR, "mainloop: Error, socket error! (rv=%d, errno=%d)", cur_ifsnr[i].sock_nr, errno);
+- exit(1);
+- }
+- bind_to_iface(cur_ifsnr[i].sock_nr, iflist[i].index);
+- ifs_change = 1;
+- }
+ else
+- {
+- /*
+- * not a new interface, socket already openen, interface already
+- * bound. Update cur_ifsnr.
+- */
+- cur_ifsnr[i].sock_nr = fsnr;
+- }
+- cur_ifsnr[i].ifindex = iflist[i].index;
+- }
+- /* Close disappeared interfaces */
+- for (i=0; i<MAXIF; ++i)
+- {
+- if ((old_ifsnr[i].sock_nr != -1) && (old_ifsnr[i].ifindex != -1) &&
+- (find_sock_nr(cur_ifsnr, old_ifsnr[i].ifindex) == -1)) {
+- NVBCR_PRINTF(("Closing an interface (it disappeared), namely: (s_nr=%d, ifidx=%d)\n", old_ifsnr[i].sock_nr, old_ifsnr[i].ifindex));
+- close(old_ifsnr[i].sock_nr);
+- old_ifsnr[i].sock_nr = -1;
+- old_ifsnr[i].ifindex = -1;
+- ifs_change = 1;
+- }
+- }
+- if (ifs_change == 1)
+- {
+- NVBCR_PRINTF(("Active interface set changed --> displaying current active interfaces..\n"));
+- if (vnologging == 0) {
+- logstr = log_interfaces;
+- logstr_cntr = sprintf(logstr, "Active interface set changed to: ");
+- logstr += logstr_cntr;
+- }
+- for (i = 0; iflist[i].index; i++)
+- {
+- NVBCR_PRINTF(("\t\tactive interface number: %d, if=(%s), sock_nr=%d\n", i, iflistToString(&(iflist[i])), cur_ifsnr[i].sock_nr));
+- if (vnologging == 0) {
+- logstr_cntr = sprintf(logstr, "%s ", iflistLogIToString(&(iflist[i]), i, &(cur_ifsnr[i])));
+- logstr += logstr_cntr;
++ {
++ no_discifs_cntr -= MAX_SELECT_WAIT;
+ }
+- }
+- if (vnologging == 0) syslog(LOG_INFO, "%s", log_interfaces);
+- ifs_change = 0;
+ }
+- }
+- else
+- {
+- no_discifs_cntr -= MAX_SELECT_WAIT;
+- }
+ }
+- }
+ }
+
+ // Discover active interfaces
+@@ -788,102 +860,102 @@ discoverActiveInterfaces(int s) {
+ /* Reset ifs */
+ memset(&ifs, 0, sizeof(ifs));
+
+- //regcomp(&preg, argv[1], REG_ICASE|REG_EXTENDED);
+- regcomp(&preg, interfaces, REG_ICASE|REG_EXTENDED);
++ regcomp(&preg, reg_interfaces, REG_ICASE|REG_EXTENDED);
+ ifs.ifc_len = MAXIF*sizeof(struct ifreq);
+ ifs.ifc_req = malloc(ifs.ifc_len);
+ ioctl(s, SIOCGIFCONF, &ifs); // Discover active interfaces
+ for (i = 0; i * sizeof(struct ifreq) < ifs.ifc_len && cntr < MAXIF; i++)
+- {
+- if (regexec(&preg, ifs.ifc_req[i].ifr_name, 0, NULL, 0) == 0) {
+-
+- /*
+- * Get interface flags and check status and type.
+- * Only if interface is up it will be used.
+- */
+- memset(&ifrflags, 0, sizeof(ifrflags));
+- strncpy(ifrflags.ifr_name, ifs.ifc_req[i].ifr_name, strlen(ifs.ifc_req[i].ifr_name));
+- if (ioctl(s, SIOCGIFFLAGS, &ifrflags) < 0) {
+- syslog(LOG_ERR, "discoverActiveInterfaces: Error, SIOCGIFFLAGS Failed! (errno=%d)", errno);
+- exit(1);
+- }
+-
+- if (ifrflags.ifr_flags & IFF_UP)
+- {
+- /*
+- * Get interface index
+- */
+- ioctl(s, SIOCGIFINDEX, &ifs.ifc_req[i]);
+-//Fix 3mar2003
+- //iflist[cntr].index = (char)ifs.ifc_req[i].ifr_ifindex;
+- iflist[cntr].index = ifs.ifc_req[i].ifr_ifindex;
+-
+- /*
+- * Get interface name
+- */
+- strncpy(iflist[cntr].ifname, ifs.ifc_req[i].ifr_ifrn.ifrn_name,
+- sizeof(iflist[cntr].ifname));
+- iflist[cntr].ifname[sizeof(iflist[cntr].ifname)-1] = 0;
++ {
++ if (regexec(&preg, ifs.ifc_req[i].ifr_name, 0, NULL, 0) == 0) {
+
+ /*
+- * Get local IP address
++ * Get interface flags and check status and type.
++ * Only if interface is up it will be used.
+ */
+- memset(&ifr, 0, sizeof(ifr));
+- ifr.ifr_addr.sa_family = AF_INET;
+- (void)strncpy(ifr.ifr_name, iflist[cntr].ifname, strlen(iflist[cntr].ifname)+1);
+- if (ioctl(s, SIOCGIFADDR, (char *)&ifr) < 0) {
+- syslog(LOG_ERR, "discoverActiveInterfaces: Error, SIOCGIFADDR Failed! (errno=%d)", errno);
++ memset(&ifrflags, 0, sizeof(ifrflags));
++ strncpy(ifrflags.ifr_name, ifs.ifc_req[i].ifr_name, strlen(ifs.ifc_req[i].ifr_name));
++ if (ioctl(s, SIOCGIFFLAGS, &ifrflags) < 0) {
++ syslog(LOG_ERR, "discoverActiveInterfaces: Error, SIOCGIFFLAGS Failed! (errno=%d)", errno);
+ exit(1);
+ }
+- sin = (struct sockaddr_in *)&ifr.ifr_addr;
+- iflist[cntr].ifaddr = ntohl(sin->sin_addr.s_addr);
+
+- iflist[cntr].flags1 = 0;
++ if (ifrflags.ifr_flags & IFF_UP)
++ {
++ /*
++ * Get interface index
++ */
++ ioctl(s, SIOCGIFINDEX, &ifs.ifc_req[i]);
++ //Fix 3mar2003
++ //iflist[cntr].index = (char)ifs.ifc_req[i].ifr_ifindex;
++ iflist[cntr].index = ifs.ifc_req[i].ifr_ifindex;
+
+- if (ifrflags.ifr_flags & IFF_POINTOPOINT) {
+- /*
+- * Get remote IP address (only for PPP interfaces)
+- */
+- memset(&ifr, 0, sizeof(ifr));
+- ifr.ifr_addr.sa_family = AF_INET;
+- (void)strncpy(ifr.ifr_name, iflist[cntr].ifname, strlen(iflist[cntr].ifname)+1);
+- if (ioctl(s, SIOCGIFDSTADDR, (char *)&ifr) < 0) {
+- syslog(LOG_ERR, "discoverActiveInterfaces: Error, SIOCGIFDSTADDR Failed! (errno=%d)", errno);
+- exit(1);
+- }
+- sin = (struct sockaddr_in *)&ifr.ifr_addr;
+- iflist[cntr].ifdstaddr = ntohl(sin->sin_addr.s_addr);
++ /*
++ * Get interface name
++ */
++ strncpy(iflist[cntr].ifname, ifs.ifc_req[i].ifr_ifrn.ifrn_name,
++ sizeof(iflist[cntr].ifname));
++ iflist[cntr].ifname[sizeof(iflist[cntr].ifname)-1] = 0;
+
+- iflist[cntr].flags1 |= IFLIST_FLAGS1_IF_IS_PPP;
+- iflist[cntr].bcast = INADDR_BROADCAST;
+- }
+- else if (ifrflags.ifr_flags & IFF_BROADCAST)
+- {
+- iflist[cntr].ifdstaddr = 0;
+- iflist[cntr].flags1 |= IFLIST_FLAGS1_IF_IS_ETH;
+- iflist[cntr].bcast = INADDR_BROADCAST;
+- }
+- else
+- {
+- iflist[cntr].ifdstaddr = 0;
+- iflist[cntr].flags1 |= IFLIST_FLAGS1_IF_IS_UNKNOWN;
+- iflist[cntr].bcast = INADDR_BROADCAST;
+- }
++ /*
++ * Get local IP address
++ */
++ memset(&ifr, 0, sizeof(ifr));
++ ifr.ifr_addr.sa_family = AF_INET;
++ (void)strncpy(ifr.ifr_name, iflist[cntr].ifname, strlen(iflist[cntr].ifname)+1);
++ if (ioctl(s, SIOCGIFADDR, (char *)&ifr) < 0) {
++ syslog(LOG_ERR, "discoverActiveInterfaces: Error, SIOCGIFADDR Failed! (errno=%d)", errno);
++ exit(1);
++ }
++ sin = (struct sockaddr_in *)&ifr.ifr_addr;
++ iflist[cntr].ifaddr = ntohl(sin->sin_addr.s_addr);
+
+- cntr++;
+- }
+- // IPSEC tunnels are a fun one. We must change the destination address
+- // so that it will be routed to the correct tunnel end point.
+- // We can define several tunnel end points for the same ipsec interface.
+- } else if (ipsec != empty && strncmp(ifs.ifc_req[i].ifr_name, "ipsec", 5) == 0) {
+- if (strncmp(ifs.ifc_req[i].ifr_name, ipsec, 6) == 0) {
+- struct hostent *hp = gethostbyname(ipsec+7);
+- ioctl(s, SIOCGIFINDEX, &ifs.ifc_req[i]);
+- iflist[cntr].index = ifs.ifc_req[i].ifr_ifindex; /* Store the SIOCGIFINDEX number */
+- memcpy(&(iflist[cntr++].bcast), hp->h_addr, sizeof(u_int32_t));
++ iflist[cntr].flags1 = 0;
++
++ if (ifrflags.ifr_flags & IFF_POINTOPOINT) {
++ /*
++ * Get remote IP address (only for PPP interfaces)
++ */
++ memset(&ifr, 0, sizeof(ifr));
++ ifr.ifr_addr.sa_family = AF_INET;
++ (void)strncpy(ifr.ifr_name, iflist[cntr].ifname, strlen(iflist[cntr].ifname)+1);
++ if (ioctl(s, SIOCGIFDSTADDR, (char *)&ifr) < 0) {
++ syslog(LOG_ERR, "discoverActiveInterfaces: Error, SIOCGIFDSTADDR Failed! (errno=%d)", errno);
++ exit(1);
++ }
++ sin = (struct sockaddr_in *)&ifr.ifr_addr;
++ iflist[cntr].ifdstaddr = ntohl(sin->sin_addr.s_addr);
++
++ iflist[cntr].flags1 |= IFLIST_FLAGS1_IF_IS_PPP;
++ iflist[cntr].bcast = INADDR_BROADCAST;
++ }
++ else if (ifrflags.ifr_flags & IFF_BROADCAST)
++ {
++ iflist[cntr].ifdstaddr = 0;
++ iflist[cntr].flags1 |= IFLIST_FLAGS1_IF_IS_ETH;
++ iflist[cntr].bcast = INADDR_BROADCAST;
++ }
++ else
++ {
++ iflist[cntr].ifdstaddr = 0;
++ iflist[cntr].flags1 |= IFLIST_FLAGS1_IF_IS_UNKNOWN;
++ iflist[cntr].bcast = INADDR_BROADCAST;
++ }
++
++ cntr++;
++ }
++ // IPSEC tunnels are a fun one. We must change the
++ // destination address so that it will be routed to the
++ // correct tunnel end point. We can define several tunnel end
++ // points for the same ipsec interface.
++ } else if (ipsec != empty && strncmp(ifs.ifc_req[i].ifr_name, "ipsec", 5) == 0) {
++ if (strncmp(ifs.ifc_req[i].ifr_name, ipsec, 6) == 0) {
++ struct hostent *hp = gethostbyname(ipsec+7);
++ ioctl(s, SIOCGIFINDEX, &ifs.ifc_req[i]);
++ iflist[cntr].index = ifs.ifc_req[i].ifr_ifindex; /* Store the SIOCGIFINDEX number */
++ memcpy(&(iflist[cntr++].bcast), hp->h_addr, sizeof(u_int32_t));
++ }
+ }
+ }
+- }
+
+ iflist[cntr].index = 0; // Terminate list
+ free(ifs.ifc_req); // Stop that leak.
+@@ -934,28 +1006,33 @@ void ip_update_checksum(unsigned char *i
+ static char *IpProtToString( unsigned char prot )
+ {
+ switch( prot )
+- {
+- case 0x11:
+- return "UDP";
+- case 0x6:
+- return "TCP";
+- case 0x2f:
+- return "GRE";
+- case 0x1:
+- return "ICMP";
+- default:
+- return "???";
+- }
++ {
++ case 0x11:
++ return "UDP";
++ case 0x6:
++ return "TCP";
++ case 0x2f:
++ return "GRE";
++ case 0x1:
++ return "ICMP";
++ default:
++ return "???";
++ }
+ }
+
+ static char *iflistToString( struct iflist *ifp )
+ {
+- static char str_tr[80+1];
++ static char str_tr[MAX_IFLOGTOSTR+90];
+
+- sprintf(str_tr, "index=%d, ifname=%s, ifaddr=%ld.%ld.%ld.%ld, ifdstaddr=%ld.%ld.%ld.%ld, flags1=0x%04lx",
++ snprintf(str_tr, sizeof(str_tr), "index=%d, ifname=%s, ifaddr=%ld.%ld.%ld.%ld, ifdstaddr=%ld.%ld.%ld.%ld, flags1=0x%04lx",
+ ifp->index, ifp->ifname,
+- (ifp->ifaddr)>>24, ((ifp->ifaddr)&0x00ff0000)>>16, ((ifp->ifaddr)&0x0000ff00)>>8, (ifp->ifaddr)&0x000000ff,
+- (ifp->ifdstaddr)>>24, ((ifp->ifdstaddr)&0x00ff0000)>>16, ((ifp->ifdstaddr)&0x0000ff00)>>8,
++ (ifp->ifaddr)>>24,
++ ((ifp->ifaddr)&0x00ff0000)>>16,
++ ((ifp->ifaddr)&0x0000ff00)>>8,
++ (ifp->ifaddr)&0x000000ff,
++ (ifp->ifdstaddr)>>24,
++ ((ifp->ifdstaddr)&0x00ff0000)>>16,
++ ((ifp->ifdstaddr)&0x0000ff00)>>8,
+ (ifp->ifdstaddr)&0x000000ff, ifp->flags1);
+
+ return str_tr;
+@@ -963,21 +1040,16 @@ static char *iflistToString( struct ifli
+
+ static char *iflistLogRToString( struct iflist *ifp, int idx, struct ifsnr *ifnr )
+ {
+- static char str_tr[MAX_IFLOGTOSTR]; /*
+- * This makes function: 1) non-reentrant (doesn't matter).
+- * 2) not useable multiple times by (s)printf.
+- */
+- sprintf(str_tr, "%s", ifp->ifname);
++ static char str_tr[MAX_IFLOGTOSTR];
++ snprintf(str_tr, sizeof(str_tr), "%s", ifp->ifname);
+ return str_tr;
+ }
+
+ static char *iflistLogIToString( struct iflist *ifp, int idx, struct ifsnr *ifnr )
+ {
+- static char str_tr[MAX_IFLOGTOSTR]; /*
+- * This makes function: 1) non-reentrant (doesn't matter).
+- * 2) not useable multiple times by (s)printf.
+- */
+- sprintf(str_tr, "%s(%d/%d/%d)", ifp->ifname, idx, ifp->index, ifnr->sock_nr);
++ static char str_tr[MAX_IFLOGTOSTR+64];
++ snprintf(str_tr, sizeof(str_tr), "%s(%d/%d/%d)", ifp->ifname,
++ idx, ifp->index, ifnr->sock_nr);
+ return str_tr;
+ }
+
+@@ -1001,10 +1073,10 @@ static void copy_ifsnr(struct ifsnr *fro
+ int i;
+
+ for (i=0; i<MAXIF; ++i)
+- {
+- to[i].sock_nr = from[i].sock_nr;
+- to[i].ifindex = from[i].ifindex;
+- }
++ {
++ to[i].sock_nr = from[i].sock_nr;
++ to[i].ifindex = from[i].ifindex;
++ }
+ }
+
+ static int find_sock_nr(struct ifsnr *l, int ifidx)
+@@ -1016,4 +1088,3 @@ static int find_sock_nr(struct ifsnr *l,
+ /* not found */
+ return -1;
+ }
+-
diff -Nru pptpd-1.4.0/debian/patches/series pptpd-1.4.0/debian/patches/series
--- pptpd-1.4.0/debian/patches/series 2013-10-20 15:32:16.000000000 +0200
+++ pptpd-1.4.0/debian/patches/series 2014-10-26 20:50:10.000000000 +0100
@@ -1,3 +1,3 @@
build_hardening-flags.patch
build_plugin.patch
-
+cherry-pick.1.4.0-11-g4ea2db6.ff.patch
Attachment:
signature.asc
Description: Digital signature