Commit 93c2b99c authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

Remove incorrect tags

parent b385b669
# Makefile for VideoLAN bridge program
# Benoit Steiner, VIA, ECP, <benny@via.ecp.fr>
############ Beginning of the configuration section ############
# Use the GNU C compiler
CC = gcc
# Use checker compiler
#CC = checkercc
# Compile debugging version
CFLAGS += -DDEBUG
# Debug with the debugger
CFLAGS += -g
# Profile with gprof. Don't strip the executable file !
#CFLAGS += -g -pg
# Compiler parameters style
CFLAGS += -Wall -O6 -static
# Use threads
CFLAGS += -D_REENTRANT
LIB += -lpthread
# Use electric fence to detect illegal memory access
LIB += -lefence
# Use ccmalloc to check memory use
#LIB += -lccmalloc -ldl
############ Beginning of the objet description section ############
OBJ = \
VLANbridge.o \
manager.o \
listener.o \
sender.o \
performer.o \
log.o \
fifo.o \
base.o \
signal.o \
pinger.o \
gratuitous.o \
route.o \
arp.o \
connect.o \
cfgfile.o \
VLANbridge: $(OBJ)
$(CC) -o $@ $(OBJ) $(LIB) $(LDFLAGS) $(CFLAGS)
chmod 755 $@
clean:
for i in $(OBJ); \
do rm -f $$i; \
done; \
rm -f core
cvsclean: clean
rm -f VLANbridge; \
rm -Rf *.o *.log
rm -Rf *~ \#*
/* VideoLAN VLANbridge
*
* Benoit Steiner, ECP, <benny@via.ecp.fr>
*
* TO DO: Mettre un timeout a l'identification pour ne pas bloquer le login
Mettre des semaphores pour que le programme ne puisse continuer avant que le manager et le listener soient completement initialises : par exemple, si une connection arrive avant que le listener n'en soit au pthread_cond_wait, le signal est perdu et le soft est bloque ; si le manager n'est pas pres, les premieres requetes du VLANserveur peuvent etre elle aussi perdues
*/
#include <unistd.h>
#include <stdio.h>
#include <netdb.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <netinet/in.h>
#include "define.h"
#include "signal.h"
#include "log.h"
#include "cfgfile.h"
#include "listener.h"
#include "performer.h"
#include "sender.h"
#include "manager.h"
#include "connect.h"
#include "VLANbridge.h"
/* Handle datas for the thread managing VLANserver requests */
struct s_Manager manager;
/* Handle datas for the thread receiving the requests from VLANserver */
struct s_Listener listener;
/* Handle datas for the thread sending the answers to the VLANserver */
struct s_Sender sender;
/* Name of the module of the program */
#define MOD_NAME MOD_VLANBRIDGE
int ConfigBridge(FILE* hCfgFile, char** pstrLogFile, char** pstrPort)
{
char* strVarName = NULL;
char* strVarVal = NULL;
int iRc = 0;
/* Find the right section */
iRc = FindCfg(hCfgFile, "Bridge");
if (iRc == CFG_OK)
{
/* Read the entries of the section */
do
{
iRc = ReadCfg(hCfgFile, &strVarName, &strVarVal);
if (iRc == CFG_OK && !strcmp(strVarName, "Port"))
{
*pstrPort = strVarVal;
Log(LOG_NOTE, MOD_NAME, "Default port is %s", *pstrPort);
}
else if (iRc == CFG_OK && !strcmp(strVarName, "Log"))
{
*pstrLogFile = strVarVal;
Log(LOG_NOTE, MOD_NAME, "Log file is %s", *pstrLogFile);
}
}
while (iRc == CFG_OK);
}
/* Test the code that made the loop terminate */
if (iRc == CFG_END)
iRc = 0;
return iRc;
}
/***************************************************************************/
/* Stop the bridge */
/***************************************************************************/
int StopBridge(int iErrorStatus)
{
int iRc = iErrorStatus;
Log(LOG_NOTE, MOD_NAME, "Exiting...");
/* Stop the listener thread if it is running */
iRc |= CancelListener(&listener);
iRc |= FreeListener(&listener);
/* Stop the manager if it is running */
iRc |= CancelManager(&manager);
iRc |= FreeManager(&manager);
/* Stop the sender if it is running */
iRc |= CancelSender(&sender);
iRc |= FreeSender(&sender);
/* Close open ressources */
iRc |= CloseConnections();
iRc |= CloseLog();
return iRc;
}
/***************************************************************************/
/* Print an help message */
/***************************************************************************/
void Usage(char* strProg)
{
#define HELP " \
Usage : %s\n \
[-c <cfg>]: Config file\n"
printf(HELP, strProg);
}
/***************************************************************************/
/* VLANbridge main function */
/***************************************************************************/
int main(int argc, char **argv)
{
int opt_arg;
int iWaitSockFd;
char* strWaitPort;
char* strLogFile;
char* strCfgFile;
FILE* pfdCfgFile = NULL;
int iRc = 0;
/* Init struuctures */
bzero(&manager, sizeof(struct s_Manager));
bzero(&listener, sizeof(struct s_Listener));
bzero(&sender, sizeof(struct s_Sender));
/* Check environnement and stop immediately if there is any problem */
if (geteuid() != 0)
{
printf("VLANbridge must be run as root: stopping\n");
exit(1);
}
if (!getprotobyname("icmp"))
{
printf("ICMP protocol is not known: stopping\n");
exit(1);
}
/* Startup message */
if (!iRc)
printf("Starting VLANbridge version %s\n\n", VERSION);
/* Variables initialisations */
if (!iRc)
{
/* Setting default values */
strCfgFile = DEFAULT_CFG; /* Default config file */
strLogFile = DEFAULT_LOG; /* Default log file */
strWaitPort = DEFAULT_PORT; /* Default port used to wait for VLANserver */
/* Parse command line */
/* First parse optional args */
opterr = 0; /* Force getopt not to generate an error message for '?' */
while ((opt_arg = getopt(argc, argv, "c:h")) != EOF)
{
switch (opt_arg)
{
case 'c':
strCfgFile = optarg;
break;
case 'h':
{
Usage(*argv);
iRc = -1;
break;
}
default:
{
printf("Invalid '%c' option or missing parameter", optopt);
Usage(*argv);
iRc = -1;
}
}
}
/* Now parse the mandatory ones */
if (argc - optind != 0)
{
printf("Invalid %d extra argument(s)", argc - optind);
Usage(*argv);
iRc = -1;
}
}
/* Open log file in order be able to trace startup process */
if (!iRc)
iRc = OpenLog(strLogFile);
/* Init the bridge */
if (!iRc)
{
/* Catch all important signals */
LogScreen(LOG_NOTE, MOD_NAME, "Initialising signal handlers...");
iRc = SetupSigHandlers();
}
if (!iRc)
{
/* Read config file */
LogScreen(LOG_NOTE, MOD_NAME, "Retriving configuration from file...");
/* Open cfg file for performer */
pfdCfgFile = OpenCfg(strCfgFile);
if (pfdCfgFile == NULL)
iRc = FILE_ERROR;
else
{
/* Global Initialisations */
iRc = ConfigBridge(pfdCfgFile, &strLogFile, &strWaitPort);
/* Initialisation of the mapping structures used by all performer threads */
iRc |= ConfigPerformer(pfdCfgFile);
}
/* Close cfg file */
iRc |= CloseCfg(pfdCfgFile);
}
if (!iRc)
{
/* Setup routing tables in order the bridge to work */
LogScreen(LOG_NOTE, MOD_NAME, "Setting up routing and arp tables...");
iRc |= InitRouting();
}
if (!iRc)
{
/* Create and init the thread that will manage the requests from VLANserver */
LogScreen(LOG_NOTE,MOD_NAME, "Starting manager thread...");
iRc = InitManager(&manager);
}
if (!iRc)
{
/* Create and init the thread that will listen to the requests from VLANserver */
LogScreen (LOG_NOTE, MOD_NAME, "Starting listener thread...");
iRc = InitListener(&listener);
}
if (!iRc)
{
/* Create and init the thread that will answer to VLANserver */
LogScreen(LOG_NOTE, MOD_NAME, "Starting sender thread...");
iRc = InitSender(&sender);
}
if (!iRc)
{
/* Open and initialise the socket who will listen for connections */
LogScreen(LOG_NOTE, MOD_NAME, "Setting up connections...");
iWaitSockFd = OpenWaitingSocket(strWaitPort);
if (iWaitSockFd <= 0)
iRc = -1;
}
/* Fork the process and stop the parent so that the VLANbridge will run in background */
//#ifndef DEBUG
// if (!iRc)
// {
// switch (fork())
// {
// case -1: /* Error: stopping now */
// {
// LogScreen(LOG_NOTE, MOD_NAME, "Unable to fork process: %s", strerror(errno));
// iRc = 1;
// break;
// }
// case 0: /* Current process is the child one: let it work */
// {
// LogScreen(LOG_NOTE, MOD_NAME, "VLANbridge now running in background");
// break;
// }
// default: /* Current process is the parent one: stop it */
// exit(0);
// }
// }
//#endif
/* The init process is now finished: start to work if there was no error, else warn that there was a pb and exit */
if (iRc)
{
/* We just printed before the operation that failed, so don't have to remind it.
The exit session is common to the normal one */
LogScreen(LOG_WARN, MOD_NAME, "An error occured: stopping bridge");
}
else
{
/* Manage incoming connections */
iRc = ProcessConnections(iWaitSockFd);
}
/* Exit process */
iRc = StopBridge(iRc);
return iRc;
}
#Fichier de configuration pour le bridge
#La section Bridge ne sert a rien pour le moment
BEGIN Bridge
Port = 2000
Log = /home/benny
END
BEGIN Performer # Config du performer
Router = 138.195.136.1 # IP du router
VLANcount = 16 # Nombre de VLANs
VLANdefault = 2 # VLAN par defaut
VLAN2 = eth0 # Mapping VLAN / If
# VLAN3 = eth1
# VLAN15 = eth2
# VLAN16 = eth3
END
/* Default server port */
#define DEFAULT_PORT "2000"
/* Default log file */
#define DEFAULT_LOG "VLANbridge.log"
/* Default config file */
#define DEFAULT_CFG "VLANbridge.cfg"
/* Software version */
#define VERSION "1.0"
int StopBridge(int iRc);
/* VideoLAN VLANbridge: Kernel ARP table management
*
* Benoit Steiner, ECP, <benny@via.ecp.fr>
*
* Known bug: Arp_Del doesn't work properly
*
* TO DO: No log is done in this module: it must be done by the performer
*/
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <errno.h>
#include "log.h"
#include "arp.h"
/* VLANbridge module name */
#define MOD_NAME MOD_PERFORMER
extern int GetDevHw (char* strIfName, struct sockaddr* psaHwAddr, int iSockFd);
/***************************************************************************/
/* Set an entry in the ARP cache */
/***************************************************************************/
int Arp_Add(struct sockaddr_in* psaAddr, char* strDev, int iSockFd)
{
int iRc = 0;
struct arpreq arReq;
/* Init the structure */
bzero (&arReq, sizeof(arReq));
/* Set the correct flags */
arReq.arp_flags = ATF_PERM; /* Permanent entry */
arReq.arp_flags |= ATF_COM; /* Complete entry */
arReq.arp_flags |= ATF_PUBL; /* Publish entry */
/* Set the host name we want to proxy for */
memcpy(&arReq.arp_pa, psaAddr, sizeof(struct sockaddr));
/* Set the device on which we want to publish the MAC */
strcpy(arReq.arp_dev, strDev);
/* Set the MAC of this device as the MAC for this entry */
iRc = GetDevHw(strDev, &arReq.arp_ha, iSockFd);
if (!iRc)
{
/* Call the kernel. */
if (ioctl(iSockFd, SIOCSARP, &arReq) < 0)
iRc = errno;
#ifdef DEBUG
else
Log (LOG_NOTE, MOD_NAME, "Proxy ARP entry for host %s on interface %s added",
inet_ntoa(((struct sockaddr_in *)psaAddr)->sin_addr), strDev);
#endif
}
if (iRc)
Log (LOG_ERROR, MOD_NAME, "Proxy ARP entry for host %s on if %s not deleted: %s",
inet_ntoa(((struct sockaddr_in *)psaAddr)->sin_addr), strDev, strerror (errno));
return iRc;
}
/***************************************************************************/
/* Delete an entry from the ARP cache */
/***************************************************************************/
int Arp_Del (struct sockaddr_in* psaAddr, char* strDev, int iSockFd)
{
int iRc = 0;
struct arpreq arReq;
/* Init the structure */
bzero(&arReq, sizeof(arReq));
/* Set the flags to only delete the entry we added with Arp_Add */
arReq.arp_flags = ATF_PERM; /* Permanent entry */
arReq.arp_flags |= ATF_PUBL; /* Public entry */
/* Set the host name we don't want to proxy for any more */
memcpy(&arReq.arp_pa, psaAddr, sizeof(struct sockaddr));
/* Select the device name on which we will delete the arp entry */
strcpy(arReq.arp_dev, strDev);
/* Call the kernel */
if (ioctl(iSockFd, SIOCDARP, &arReq) < 0)
iRc = errno;
#ifdef DEBUG
else
Log (LOG_NOTE, MOD_NAME, "Proxy ARP entry for host %s on interface %s deleted",
inet_ntoa(((struct sockaddr_in *)psaAddr)->sin_addr), strDev);
#endif
if (iRc)
Log (LOG_ERROR, MOD_NAME, "Pproxy ARP entry for host %s on if %s not deleted: %s",
inet_ntoa(((struct sockaddr_in *)psaAddr)->sin_addr), strDev, strerror (errno));
return iRc;
}
/* VideoLAN VLANbridge : Kernel ARP table management
*
* Definition file
*
* You need to include <sys/socket.h> before including this file
*/
#ifndef _ARP_H
#define _ARP_H
int Arp_Del (struct sockaddr_in* psaAddr, char* strDev, int iSockFd);
int Arp_Add (struct sockaddr_in* psaAddr, char* strDev, int iSockFd);
#endif
VLANarp: VLANarp.o arp.o log.o
gcc -Wall -static -DDEBUG -o VLANarp VLANarp.o arp.o log.o
VLANarp.o: VLANarp.c arp.h
gcc -Wall -static -DDEBUG -c VLANarp.c
arp.o: arp.c arp.h
gcc -Wall -static -DDEBUG -c arp.c
log.o: ../log.c ../log.h
gcc -Wall -static -DDEBUG -c ../log.c
#include <netdb.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include "arp.h"
int sockfd=0; /* active socket descriptor */
int main(int argc, char **argv)
{
char host[] = "bs.via.ecp.fr";
struct sockaddr_in target;
unsigned long inaddr;
struct hostent *hp;
int i = 0;
bzero (&target, sizeof (struct sockaddr_in));
target.sin_family = AF_INET;
if ( (inaddr = inet_addr(host)) != INADDR_NONE)
{ /* it's dotted-decimal */
bcopy(&inaddr, &target.sin_addr, sizeof(inaddr));
}
else
{ if ( (hp = gethostbyname(host)) == NULL)
return -1;
bcopy(hp->h_addr, &target.sin_addr, hp->h_length);
};
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) <0)
{
printf ("Can't open socket\n");
exit(-1);
};
printf("Sockfd : %d\n", sockfd);
i = Arp_Add (&target, "eth0", sockfd);
printf ("1: %d\n", i);
i = Arp_Add (&target, "eth0", sockfd);
printf ("2: %d\n",i) ;
sleep (10);
i = Arp_Del (&target, "eth0", sockfd);
printf ("3: %d\n", i);
return (0);
}
/* VideoLAN VLANbridge: Kernel ARP table management
*
* Benoit Steiner, ECP, <benny@via.ecp.fr>
*
* Known bug: Arp_Del doesn't work properly
*
* TO DO: No log is done in this module: it must be done by the performer
*/
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include "../log.h"
#include "arp.h"
/* VLANbridge module name */
#define MOD_NAME MOD_PERFORMER
/***************************************************************************/
/* Get the hardware address to a specified interface name */
/***************************************************************************/
int GetDevHw (char* strIfName, struct sockaddr* psaHwAddr, int iSockFd)
{
int iRc = 0;
struct ifreq ifrRequest;
/* Get hardware address of the device */
strcpy(ifrRequest.ifr_name, strIfName);
if (ioctl(iSockFd, SIOCGIFHWADDR, &ifrRequest) < 0 )
{
Log (LOG_WARN, MOD_NAME, "Unable to retrieve %s MAC address: %s\n",
strIfName, strerror (errno));
iRc = errno;
}
/* Copy it to the sockaddr struct */
if (!iRc)
memcpy(psaHwAddr, &(ifrRequest.ifr_hwaddr), sizeof(struct sockaddr));
return(iRc);
};
/***************************************************************************/
/* Set an entry in the ARP cache */
/***************************************************************************/
int Arp_Add(struct sockaddr_in* psaAddr, char* strDev, int iSockFd)
{
int iRc = 0;
struct arpreq arReq;
/* Init the structure */
bzero (&arReq, sizeof(arReq));
/* Set the correct flags */
arReq.arp_flags = ATF_PERM; /* Permanent entry */
arReq.arp_flags |= ATF_COM; /* Complete entry */
arReq.arp_flags |= ATF_PUBL; /* Publish entry */
/* Set the host name we want to proxy for */
memcpy(&arReq.arp_pa, psaAddr, sizeof(struct sockaddr));
/* Set the device on which we want to publish the MAC */
strcpy(arReq.arp_dev, strDev);
/* Set the MAC of this device as the MAC for this entry */
iRc = GetDevHw(strDev, &arReq.arp_ha, iSockFd);