/*  
    Tentun

    Derived from VTun by Max K.

    Copyright (C) 2003 David Gordon davidgordonca@hotmail.com

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
 */

#include "config.h"
 
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <strings.h>
#include <string.h>
#include <errno.h>
#include <sys/time.h>
#include <time.h>

#ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#endif

#ifdef HAVE_SCHED_H
#include <sched.h>
#endif

#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif

#include "plugins.h"


struct plug_mod *plug_mod_head = NULL, *plug_mod_tail = NULL;

/* Modules functions*/

/* Add module to the end of modules list */
void plug_add_mod(struct plug_mod *mod)
{
     if( !plug_mod_head ){
        plug_mod_head = plug_mod_tail = mod;
	mod->next = mod->prev = NULL;
     } else {
        plug_mod_tail->next = mod;
        mod->prev = plug_mod_tail;
        mod->next = NULL;
        plug_mod_tail = mod;
     }
}

/*  Initialize and allocate each module */
int plug_alloc_mod(struct tentun_host *host)
{
     struct plug_mod *mod = plug_mod_head;

     while( mod ){
        if( mod->alloc && (mod->alloc)(host) )
	   return 1; 
	mod = mod->next;
     } 

     return 0;
}

/* Free all modules */
int plug_free_mod(void)
{
     struct plug_mod *mod = plug_mod_head;

     while( mod ){
        if( mod->free && (mod->free)() )
	   return 1;
	mod = mod->next;
     } 
     plug_mod_head = plug_mod_tail = NULL;
     return 0;
}

 /* Run modules down (from head to tail) */
inline int plug_run_down(int len, char *in, char **out)
{
     register struct plug_mod *mod;
     
     *out = in;
     for(mod = plug_mod_head; mod && len > 0; mod = mod->next )
        if( mod->encode ){
           len = (mod->encode)(len, in, out);
           in = *out;
        }
     return len;
}

/* Run modules up (from tail to head) */
inline int plug_run_up(int len, char *in, char **out)
{
     register struct plug_mod *mod;
     
     *out = in;
     for(mod = plug_mod_tail; mod && len > 0; mod = mod->prev )
        if( mod->decode ){
	   len = (mod->decode)(len, in, out);
           in = *out;
	}
     return len;
}

/* Check if modules are accepting the data(down) */
inline int plug_check_down(void)
{
     register struct plug_mod *mod;
     int err = 1;
 
     for(mod = plug_mod_head; mod && err > 0; mod = mod->next )
        if( mod->avail_encode )
           err = (mod->avail_encode)();
     return err;
}

/* Check if modules are accepting the data(up) */
inline int plug_check_up(void)
{
     register struct plug_mod *mod;
     int err = 1;

     for(mod = plug_mod_tail; mod && err > 0; mod = mod->prev)
        if( mod->avail_decode )
           err = (mod->avail_decode)();

     return err;
}
		
