Subject: Cherry-pick 1.4.0-11-g4ea2db6 ff. to fix sprintf usage Origin: commit 4ea2db6028cc1079aa84ac1b92e23ba8a7ce9d8e commit 2521c45c19106722f299c66d4e0ef86ff7486b54 commit eee8ad1adece7cc5dfcadaa3cf838cfaf0b01b05 Author: James Cameron Date: Thu Oct 16 08:22:36 2014 +1100 Bug-Debian: https://bugs.debian.org/765442 Last-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 // Ditto on the no responsibility. // -// Rewritten by Norbert van Bolhuis 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 +// 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 ] Defines from which interface broadcasts will be relayed.\n"); - printf(" [-n] [--nolog] No logging/tracing to /var/log/messages.\n"); - printf(" [-o] [--outgoing ] Defines to which interface broadcasts will be relayed.\n"); - printf(" [-s] [--ipsec ] 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 ] Defines from which interface broadcasts will be relayed.\n"); + printf(" [-n] [--nolog] No logging/tracing to /var/log/messages.\n"); + printf(" [-o] [--outgoing ] Defines to which interface broadcasts will be relayed.\n"); + printf(" [-s] [--ipsec ] 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 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 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 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 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