// nullPlugin plugin
//
// Does nothing. Just used to measure plugin overrhead.
//

#include "stdinc.h"

#include "nullPlugin.h"

MOD_MISC("nullPlugin")

//
// Static plugin class structure. Defined for the CLASS, not each instance.
// Change only the name
//
static struct rp_class nullPlugin_class;

//
// Create and initialize an instance of nullPlugin.
//
// This is where we initialize any per instance variables.
// Most of this code is standard stuff and should be left
// unchanged, except for the plugin name.
//
struct rp_instance * nullPlugin_create_instance(
	struct rp_class *theClass,	// pointer to class structure
	u_int32_t instanceid		// identifier for new instance
) {
	struct nullPlugin_instance *newInst; 

	// Allocate memory for new instance of nullPlugin.
	MSR_PLUGIN_MALLOC(newInst, struct nullPlugin_instance *, 
	                  sizeof(struct nullPlugin_instance),
	                  M_MSR, 
	                  M_WAITOK);
	if (newInst == NULL) return NULL;

	// Fill in instance pointers to local methods
	newInst->rootinstance.rpclass         = &nullPlugin_class;
	newInst->rootinstance.handle_packet   = nullPlugin_handle_packet;
	newInst->rootinstance.free_instance   = nullPlugin_free_instance;
	newInst->rootinstance.bind_instance   = nullPlugin_bind_instance;
	newInst->rootinstance.unbind_instance = nullPlugin_unbind_instance;
	newInst->rootinstance.handle_msg      = nullPlugin_handle_msg;

	newInst->rootinstance.instanceid = instanceid;

	//
	// Initialization of per instance variables goes here.
	//
	// none

	return (struct rp_instance *) newInst;
}

//
// Handle an incoming packet.
//
void nullPlugin_handle_packet(
	struct rp_instance *this,	// pointer to instance structure
	void *bufferList		// pointer to list of packet buffers
) {

  MSR_DEBUG((MSR_DEBUG_PLUGIN | MSR_DEBUG_LEVEL_INFO,
				"nullPlugin_handle_packet called\n"));

}

//
// Handle a control message.
//
// The message is simply a list of integers. The first integer defines
// a message type. The remaining values can be used to specify parameters.
// A response can be returned by over-writing the values in the message buffer.
// The length argument must be updated correctly, to indicate the size of the
// response. Length of message and response limited to xx bytes.
//
// nullPlugin defines no message types
//

int nullPlugin_handle_msg(
	struct rp_instance *this,	// pointer to instance structure
	void *buf,			// buffer containing integer values
					// buf[0]=instance id
					// buf[1]=command type
					// buf[2]=first parameter value
					// buf[3]=second parameter value ...
	u_int8_t flags,			// ignore
	u_int8_t seq,			// sequence number of message
	u_int8_t *len			// number of values in buf
) {
	return 0;
}

//
// Free instance structure.
//
void nullPlugin_free_instance(struct rp_instance *this) {
	// perform any cleanup of per-instance data structures that
	// may be required.
}

//
// Bind/unbind plugin instance to/from a filter
//
void nullPlugin_bind_instance(struct rp_instance *this) {
	// perform any initialization that should be done whenever the
	// plugin is bound to a filter
}

void nullPlugin_unbind_instance(struct rp_instance *this) {
	// perform any cleanup that should be done whenever the
	// plugin is unbound a filter

}

//
// The remaining code is standard stuff. The only thing that you
// typically need to change is the various places where the
// plugin name (nullPlugin) appears in function and type names.
//

//
// Initialize the class. 
//
void nullPlugin_init_class() {
	nullPlugin_class.classid = nullPlugin_ID;
	nullPlugin_class.itype = RP_INTERFACE_TYPE_HLIST;
	nullPlugin_class.create_instance = nullPlugin_create_instance;
	return;
}

//
// Return class structure
//
struct rp_class * nullPlugin_get_class() {
	return &nullPlugin_class;
}

//
// External kernel module entry point.
//
// It is called each time the class is loaded or unloaded.
// The stat information is not needed here, so we will 
// leave it lkm_nofunc().
//

int nullPlugin(struct lkm_table *lkmtp, int cmd, int ver,
		struct kernel_plugin_fct_struct *fctPtr) {
	// Do NOT put anything before the kernel_plugin_fcts is set,
	// especially if it uses any of the MSR_ macros!!!
	if (kernel_plugin_fcts == NULL) {
		kernel_plugin_fcts = fctPtr;
	  	kernel_plugin_variables = fctPtr->pluginVariables;
	}
	
	MSR_PLUGIN_DISPATCH(lkmtp, cmd, ver, nullPlugin_load,
			nullPlugin_unload, PLUGIN_LKM_NOFUNC_FCT);
}

//
// Load class. This function is called each time the class is loaded
//
int nullPlugin_load(struct lkm_table *lkmtp, int cmd) {
	int err;

	if (PLUGIN_LKM_EXISTS_FCT(lkmtp)) { // avoid loading twice
		return (EEXIST);
	}
	nullPlugin_init_class();

	err = PLUGIN_PCU_REGISTER_CLASS_FCT(nullPlugin_get_class());
	if (err != RP_OK) {
		return -1;
	}

	return 0;
}

//
// Unload class. This function is called each time the class is unloaded.
// Remove all existing instances and then remove class.
//
int nullPlugin_unload(struct lkm_table *lkmtp, int cmd) {
	struct rp_class *rpclass;
	u_int32_t cid;

	rpclass = nullPlugin_get_class();
	cid = rpclass->classid;

	if (PLUGIN_PCU_FREE_ALL_INSTANCES_FCT(rpclass) != RP_OK) {
		return -1;
	}

	return 0;
}
