#include <ByteOrder.h>
#include <net_buffer.h>
#include <net_stack.h>
#include <KPPPConfigurePacket.h>
#include <KPPPInterface.h>
#include <arpa/inet.h>
KPPPConfigurePacket::KPPPConfigurePacket(uint8 code)
: fCode(code),
fID(0)
{
}
KPPPConfigurePacket::KPPPConfigurePacket(net_buffer *packet)
{
NetBufferHeaderReader<ppp_lcp_packet> bufferhead(packet);
if (bufferhead.Status() != B_OK)
return;
ppp_lcp_packet &header = bufferhead.Data();
SetID(header.id);
if (!SetCode(header.code))
return;
uint16 length = ntohs(header.length);
if (length < 6 || length > packet->size)
return;
int32 position = 0;
ppp_configure_item *item;
while (position < length - 4) {
item = (ppp_configure_item*) (header.data + position);
if (item->length < 2)
return;
position += item->length;
AddItem(item);
}
}
KPPPConfigurePacket::~KPPPConfigurePacket()
{
for (int32 index = 0; index < CountItems(); index++)
free(ItemAt(index));
}
bool
KPPPConfigurePacket::SetCode(uint8 code)
{
if (code < PPP_CONFIGURE_REQUEST || code > PPP_CONFIGURE_REJECT)
return false;
fCode = code;
return true;
}
bool
KPPPConfigurePacket::AddItem(const ppp_configure_item *item, int32 index)
{
if (!item || item->length < 2)
return false;
ppp_configure_item *add = (ppp_configure_item*) malloc(item->length);
memcpy(add, item, item->length);
bool status;
if (index < 0)
status = fItems.AddItem(add);
else
status = fItems.AddItem(add, index);
if (!status) {
free(add);
return false;
}
return true;
}
bool
KPPPConfigurePacket::RemoveItem(ppp_configure_item *item)
{
if (!fItems.HasItem(item))
return false;
fItems.RemoveItem(item);
free(item);
return true;
}
ppp_configure_item*
KPPPConfigurePacket::ItemAt(int32 index) const
{
ppp_configure_item *item = fItems.ItemAt(index);
if (item == fItems.GetDefaultItem())
return NULL;
return item;
}
ppp_configure_item*
KPPPConfigurePacket::ItemWithType(uint8 type) const
{
ppp_configure_item *item;
for (int32 index = 0; index < CountItems(); index++) {
item = ItemAt(index);
if (item && item->type == type)
return item;
}
return NULL;
}
net_buffer*
KPPPConfigurePacket::ToNetBuffer(uint32 MRU)
{
net_buffer *buffer = gBufferModule->create(256);
if (buffer == NULL) {
TRACE("%s::%s: gBufferModule->create fail\n", __FILE__, __func__);
return(NULL);
}
ppp_lcp_packet *header;
status_t status = gBufferModule->append_size(buffer, 1492, (void **)&header);
if (status != B_OK) {
TRACE("%s::%s: gBufferModule->append_size\n", __FILE__, __func__);
gBufferModule->free(buffer);
return(NULL);
}
header->code = Code();
header->id = ID();
uint16 length = 0;
ppp_configure_item *item;
for (int32 index = 0; index < CountItems(); index++) {
item = ItemAt(index);
if (MRU - length < item->length) {
gBufferModule->free(buffer);
return NULL;
}
memcpy(header->data + length, item, item->length);
length += item->length;
}
length += 4;
header->length = htons(length);
status = gBufferModule->trim(buffer, length);
if (status < B_OK) {
dprintf("%s::%s: gBufferModule->trim\n", __FILE__, __func__);
gBufferModule->free(buffer);
return(NULL);
}
return buffer;
}