#ifndef KPI_MBUF_H
#define KPI_MBUF_H


//#include <HYS/sys/kpi_mbuf.h>
//#ifndef   SYS_KERNELTYPES_H
#include <sys/kernel_types.h>
//#endif

#include <mach/vm_types.h>
#include <sys/errno.h>//hys

#include <APPLE/sys/kpi_mbuf.h>


/*mbuf_type_t


Types of mbufs. 
enum { 
    MBUF_TYPE_FREE = 0, // should be on free list 
    MBUF_TYPE_DATA = 1, // dynamic (data) allocation 
    MBUF_TYPE_HEADER = 2, // packet header 
    MBUF_TYPE_SOCKET = 3, // socket structure 
    MBUF_TYPE_PCB = 4, // protocol control block 
    MBUF_TYPE_RTABLE = 5, // routing tables 
    MBUF_TYPE_HTABLE = 6, //IMP host tables 
    MBUF_TYPE_ATABLE = 7, // address resolution tables 
    MBUF_TYPE_SONAME = 8, // socket name 
    MBUF_TYPE_SOOPTS = 10, // socket options 
    MBUF_TYPE_FTABLE = 11, // fragment reassembly header 
    MBUF_TYPE_RIGHTS = 12, // access rights 
    MBUF_TYPE_IFADDR = 13, //interface address 
    MBUF_TYPE_CONTROL = 14, // extra-data protocol message 
    MBUF_TYPE_OOBDATA = 15 //expedited data 
};  
Constants
MBUF_TYPE_FREE
Indicates the mbuf is free and is sitting on the queue of free mbufs. If you find that an mbuf you have a reference to has this type, something has gone terribly wrong.
MBUF_TYPE_DATA
Indicates this mbuf is being used to store data.
MBUF_TYPE_HEADER
Indicates this mbuf has a packet header, this is probably a packet.
MBUF_TYPE_SOCKET
Socket structure.
MBUF_TYPE_PCB
Protocol control block.
MBUF_TYPE_RTABLE
Routing table entry.
MBUF_TYPE_HTABLE
IMP host tables???.
MBUF_TYPE_ATABLE
Address resolution table data.
MBUF_TYPE_SONAME
Socket name, usually a sockaddr of some sort.
MBUF_TYPE_FTABLE
Fragment reassembly header.
MBUF_TYPE_RIGHTS
Access rights.
MBUF_TYPE_IFADDR
Interface address.
MBUF_TYPE_CONTROL
Extra-data protocol message (control message).
MBUF_TYPE_OOBDATA
Out of band data.
Discussion 

Some mbufs represent packets, some represnt data waiting on sockets. Other mbufs store control data or other various structures. The mbuf type is used to store what sort of data the mbuf contains.*/
enum { 
    MBUF_TYPE_FREE = 0, // should be on free list 
    MBUF_TYPE_DATA = 1, // dynamic (data) allocation 
    MBUF_TYPE_HEADER = 2, // packet header 
    MBUF_TYPE_SOCKET = 3, // socket structure 
    MBUF_TYPE_PCB = 4, // protocol control block 
    MBUF_TYPE_RTABLE = 5, // routing tables 
    MBUF_TYPE_HTABLE = 6, //IMP host tables 
    MBUF_TYPE_ATABLE = 7, // address resolution tables 
    MBUF_TYPE_SONAME = 8, // socket name 
    MBUF_TYPE_SOOPTS = 10, // socket options 
    MBUF_TYPE_FTABLE = 11, // fragment reassembly header 
    MBUF_TYPE_RIGHTS = 12, // access rights 
    MBUF_TYPE_IFADDR = 13, //interface address 
    MBUF_TYPE_CONTROL = 14, // extra-data protocol message 
    MBUF_TYPE_OOBDATA = 15 //expedited data 
};  

/*mbuf_how_t


Method of allocating an mbuf. 
enum { 
    MBUF_WAITOK = 0, //Ok to block to get memory 
    MBUF_DONTWAIT = 1 //Don't block, fail if blocking would be required 
};  
Constants
MBUF_WAITOK
Allow a call to allocate an mbuf to block.
MBUF_DONTWAIT
Don't allow the mbuf allocation call to block, if blocking is necessary fail and return immediately.
Discussion 

Blocking will cause the funnel to be dropped. If the funnel is dropped, other threads may make changes to networking data structures. This can lead to very bad things happening. Blocking on the input or output path can also impact performance. There are some cases where making a blocking call is acceptable. When in doubt, use MBUF_DONTWAIT.*/
enum { 
    MBUF_WAITOK = 0, /* Ok to block to get memory */
    MBUF_DONTWAIT = 1 /* Don't block, fail if blocking would be required */
};  

//functions

/*mbuf_freem

void mbuf_freem(
    mbuf_t mbuf);  
Parameters
mbuf
The first mbuf in the chain to free.
Discussion 

Frees a chain of mbufs link through mnext.*/
void mbuf_freem(
    mbuf_t mbuf);  

/*mbuf_setnext

errno_t mbuf_setnext(
    mbuf_t mbuf,
    mbuf_t next);  
Parameters
mbuf
The mbuf.
next
The new next mbuf.
Return Value

0 upon success otherwise the errno error. 
Discussion 

Sets the next mbuf in the chain.*/
errno_t mbuf_setnext(
    mbuf_t mbuf,
    mbuf_t next);  

/*mbuf_setnextpkt

void mbuf_setnextpkt(
    mbuf_t mbuf,
    mbuf_t nextpkt);  
Parameters
mbuf
The mbuf.
nextpkt
The new next packet.
Discussion 

Sets the next packet attached to this mbuf.*/
void mbuf_setnextpkt(
    mbuf_t mbuf,
    mbuf_t nextpkt);  

/*mbuf_nextpkt

mbuf_t mbuf_nextpkt(
    mbuf_t mbuf);  
Parameters
mbuf
The mbuf.
Return Value

The nextpkt. 
Discussion 

Gets the next packet from the mbuf.*/
mbuf_t mbuf_nextpkt(
    mbuf_t mbuf);  

/*mbuf_pkthdr_setlen

void mbuf_pkthdr_setlen(
    mbuf_t mbuf,
    size_t len);  
Parameters
mbuf
The mbuf containing the packet header.
len
The new length of the packet.
Return Value

0 upon success otherwise the errno error. 
Discussion 

Sets the length of the packet in the packet header.*/

void mbuf_pkthdr_setlen(
    mbuf_t mbuf,
    size_t len);  

/*mbuf_setlen

void mbuf_setlen(
    mbuf_t mbuf,
    size_t len);  
Parameters
mbuf
The mbuf.
len
The new length.
Return Value

0 upon success otherwise the errno error. 
Discussion 

Sets the length of data in this packet. Be careful to not set the length over the space available in the mbuf.*/
void mbuf_setlen(
    mbuf_t mbuf,
    size_t len);  

/*mbuf_pkthdr_setrcvif

errno_t mbuf_pkthdr_setrcvif(
    mbuf_t mbuf,
    ifnet_t ifnet);  
Parameters
mbuf
The mbuf containing the packet header.
ifnet
A reference to an interface.
Return Value

0 upon success otherwise the errno error. 
Discussion 

Sets the interface the packet was received on.*/
errno_t mbuf_pkthdr_setrcvif(
    mbuf_t mbuf,
    ifnet_t ifnet);  

/*mbuf_tag_find

errno_t mbuf_tag_find(
    mbuf_t mbuf,
    mbuf_tag_id_t module_id, 
    mbuf_tag_type_t type,
    size_t *length,
    void** data_p);  
Parameters
mbuf
The mbuf the tag is attached to.
module_id
A module identifier returned by mbuf_tag_id_find.
type
The 16 bit type of the tag to find.
length
Upon success, the length of data will be store in *length.
data_p
Upon successful return, *data_p will point to the buffer allocated for the mtag.
Return Value

0 upon success otherwise the errno error. 
Discussion 

Find the data associated with an mbuf tag.*/
errno_t mbuf_tag_find(
    mbuf_t mbuf,
    mbuf_tag_id_t module_id, 
    mbuf_tag_type_t type,
    size_t *length,
    void** data_p);  

/*mbuf_tag_allocate

errno_t mbuf_tag_allocate(
    mbuf_t mbuf,
    mbuf_tag_id_t module_id, 
    mbuf_tag_type_t type,
    size_t length, 
    mbuf_how_t how,
    void** data_p);  
Parameters
mbuf
The mbuf to attach this tag to.
module_id
A module identifier returned by mbuf_tag_id_find.
type
A 16 bit type value. For a given module_id, you can use a number of different tag types.
length
The length, in bytes, to allocate for storage that will be associated with this tag on this mbuf.
how
Indicate whether you want to block and wait for memory if memory is not immediately available.
data_p
Upon successful return, *data_p will point to the buffer allocated for the mtag.
Return Value

0 upon success otherwise the errno error. 
Discussion 

Allocate an mbuf tag. Mbuf tags allow various portions of the stack to tag mbufs with data that will travel with the mbuf through the stack. 

Tags may only be added to mbufs with packet headers (MBUF_PKTHDR flag is set). Mbuf tags are freed when the mbuf is freed or when mbuf_tag_free is called.*/
errno_t mbuf_tag_allocate(
    mbuf_t mbuf,
    mbuf_tag_id_t module_id, 
    mbuf_tag_type_t type,
    size_t length, 
    mbuf_how_t how,
    void** data_p);  

/*mbuf_flags

mbuf_flags_t mbuf_flags(
    mbuf_t mbuf);  
Parameters
mbuf
The mbuf.
Return Value

The flags. 
Discussion 

Returns the set flags.*/
mbuf_flags_t mbuf_flags(
    mbuf_t mbuf);  

/*mbuf_len

size_t mbuf_len(
    mbuf_t mbuf);  
Parameters
mbuf
The mbuf.
Return Value

The length. 
Discussion 

Gets the length of data in this mbuf.*/
size_t mbuf_len(
    mbuf_t mbuf);  

/*mbuf_next

mbuf_t mbuf_next(
    mbuf_t mbuf);  
Parameters
mbuf
The mbuf.
Return Value

The next mbuf in the chain. 
Discussion 

Returns the next mbuf in the chain.*/
mbuf_t mbuf_next(
    mbuf_t mbuf);  

/*mbuf_gethdr

errno_t mbuf_gethdr(
    mbuf_how_t how,
    mbuf_type_t type,
    mbuf_t*mbuf);  
Parameters
how
Blocking or non-blocking.
type
The type of the mbuf.
mbuf
The mbuf.
Return Value

0 on success, errno error on failure. 
Discussion 

Allocates an mbuf without a cluster for external data. Sets a flag to indicate there is a packet header and initializes the packet header.*/
errno_t mbuf_gethdr(
    mbuf_how_t how,
    mbuf_type_t type,
    mbuf_t*mbuf);  

/*mbuf_pkthdr_len

size_t mbuf_pkthdr_len(
    mbuf_t mbuf);  
Parameters
mbuf
The mbuf containing the packet header with the length to be changed.
Return Value

The length, in bytes, of the packet. 
Discussion 

Returns the length as reported by the packet header.*/
size_t mbuf_pkthdr_len(
    mbuf_t mbuf);  

/*mbuf_tag_id_find

errno_t mbuf_tag_id_find(
    const char *module_string, 
    mbuf_tag_id_t *module_id);  
Parameters
module_string
A unique string identifying your module. Example: com.apple.nke.SharedIP.
module_id
Upon return, a unique identifier for use with mbuf_tag_* functions. This identifier is valid until the machine is rebooted.
Return Value

0 upon success otherwise the errno error. 
Discussion 

Lookup the module id for a string. If there is no module id assigned to this string, a new module id will be assigned. The string should be the bundle id of the kext. In the case of a tag that will be shared across multiple kexts, a common bundle id style string should be used. 

The lookup operation is not optimized. A module should call this function once during startup and chache the module id. The module id will not be resassigned until the machine reboots.*/
errno_t mbuf_tag_id_find(
    const char *module_string, 
    mbuf_tag_id_t *module_id);  

/*mbuf_data

void* mbuf_data(
    mbuf_t mbuf);  
Parameters
mbuf
The mbuf.
Return Value

A pointer to the data in the mbuf. 
Discussion 

Returns a pointer to the start of data in this mbuf. There may be additional data on chained mbufs. The data you're looking for may not be contiguous if it spans more than one mbuf. Use mbuf_len to determine the lenght of data available in this mbuf. If a data structure you want to access stradles two mbufs in a chain, either use mbuf_pullup to get the data contiguous in one mbuf or copy the pieces of data from each mbuf in to a contiguous buffer. Using mbuf_pullup has the advantage of not having to copy the data. On the other hand, if you don't make sure there is space in the mbuf, mbuf_pullup may fail and free the mbuf.*/
void* mbuf_data(
    mbuf_t mbuf);  


#endif