| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479 | Subject: Cherry-pick 1.4.0-11-g4ea2db6 ff. to fix sprintf usageOrigin:    commit 4ea2db6028cc1079aa84ac1b92e23ba8a7ce9d8e    commit 2521c45c19106722f299c66d4e0ef86ff7486b54    commit eee8ad1adece7cc5dfcadaa3cf838cfaf0b01b05Author: James Cameron <quozl@laptop.org>Date: Thu Oct 16 08:22:36 2014 +1100Bug-Debian: https://bugs.debian.org/765442Last-Update: 2015-08-24--- 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 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 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 @@  /*  * 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 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 @@   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 @@ {   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 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 @@     /*-   * 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 @@   }   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 @@   /* 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 @@ 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 *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 @@   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 @@   /* not found */   return -1; }-
 |