vfs: check userland buffers before reading them.
[haiku.git] / src / add-ons / kernel / network / ppp / pppoe / DiscoveryPacket.cpp
blobafb43c016243979223026a54d91ee655031853bf
1 /*
2 * Copyright 2003-2004, Waldemar Kornewald <wkornew@gmx.net>
3 * Distributed under the terms of the MIT License.
4 */
6 #include <ByteOrder.h>
7 #include <NetBufferUtilities.h>
8 #include <net_buffer.h>
10 #include "DiscoveryPacket.h"
12 DiscoveryPacket::DiscoveryPacket(uint8 code, uint16 sessionID)
13 : fCode(code),
14 fSessionID(sessionID),
15 fInitStatus(B_OK)
20 DiscoveryPacket::DiscoveryPacket(net_buffer *packet, uint32 start)
22 // decode packet
23 NetBufferHeaderReader<pppoe_header> bufferheader(packet);
24 if (bufferheader.Status() != B_OK) {
25 dprintf("NetBufferHeaderReader create fail\n");
26 fInitStatus = B_ERROR;
27 return;
29 pppoe_header &header = bufferheader.Data();
31 SetCode(header.code);
33 uint16 length = ntohs(header.length);
35 if(length > packet->size - PPPoE_HEADER_SIZE) {
36 dprintf("packet size less than pppoe payload\n");
37 dprintf("pppoe payload: %d\n", length);
38 dprintf("PPPoE_HEADER_SIZE: %d\n", PPPoE_HEADER_SIZE);
39 dprintf("packet->size: %" B_PRIu32 "\n", packet->size);
40 fInitStatus = B_ERROR;
41 return;
42 // there are no tags (or one corrupted tag)
45 int32 position = 0;
46 pppoe_tag *tag;
48 while(position <= length - 4) {
49 tag = (pppoe_tag*) (header.data + position);
50 position += ntohs(tag->length) + 4;
52 AddTag(ntohs(tag->type), tag->data, ntohs(tag->length));
55 fInitStatus = B_OK;
59 DiscoveryPacket::~DiscoveryPacket()
61 for(int32 index = 0; index < CountTags(); index++)
62 free(TagAt(index));
66 bool
67 DiscoveryPacket::AddTag(uint16 type, const void *data, uint16 length, int32 index)
69 pppoe_tag *add = (pppoe_tag*) malloc(length + 4);
70 add->type = type;
71 add->length = length;
72 memcpy(add->data, data, length);
74 bool status;
75 if(index < 0)
76 status = fTags.AddItem(add);
77 else
78 status = fTags.AddItem(add, index);
79 if(!status) {
80 free(add);
81 return false;
84 return true;
88 bool
89 DiscoveryPacket::RemoveTag(pppoe_tag *tag)
91 if(!fTags.HasItem(tag))
92 return false;
94 fTags.RemoveItem(tag);
95 free(tag);
97 return true;
101 pppoe_tag*
102 DiscoveryPacket::TagAt(int32 index) const
104 pppoe_tag *tag = fTags.ItemAt(index);
106 if(tag == fTags.GetDefaultItem())
107 return NULL;
109 return tag;
113 pppoe_tag*
114 DiscoveryPacket::TagWithType(uint16 type) const
116 pppoe_tag *tag;
118 for(int32 index = 0; index < CountTags(); index++) {
119 tag = TagAt(index);
120 if(tag && tag->type == type)
121 return tag;
124 return NULL;
128 net_buffer*
129 DiscoveryPacket::ToNetBuffer(uint32 MTU)
131 net_buffer *packet = gBufferModule->create(256);
132 if (packet == NULL) {
133 dprintf("create buffer failure\n");
134 return NULL;
137 pppoe_header *header ;
138 status_t status = gBufferModule->append_size(packet, 1492, (void **)&header);
139 if (status != B_OK) {
140 dprintf("append size failure\n");
141 return NULL;
144 header->version = PPPoE_VERSION;
145 header->type = PPPoE_TYPE;
146 header->code = Code();
147 header->sessionID = SessionID();
149 uint16 length = 0;
150 pppoe_tag *tag;
152 for(int32 index = 0; index < CountTags(); index++) {
153 tag = TagAt(index);
155 // make sure we have enough space left
156 if(MTU - length < tag->length) {
157 gBufferModule->free(packet);
158 return NULL;
161 *((uint16*)(header->data + length)) = htons(tag->type);
162 length += 2;
163 *((uint16*)(header->data + length)) = htons(tag->length);
164 length += 2;
165 memcpy(header->data + length, tag->data, tag->length);
166 length += tag->length;
169 header->length = htons(length);
170 status = gBufferModule->trim(packet, length + PPPoE_HEADER_SIZE);
171 if (status != B_OK) {
172 dprintf("trim buffer failure\n");
173 return NULL;
176 return packet;