xref: /haiku/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPConfigurePacket.cpp (revision bab64f65bb775dc23060e276f1f1c4498ab7af6c)
1 /*
2  * Copyright 2003-2007, Waldemar Kornewald <wkornew@gmx.net>
3  * Distributed under the terms of the MIT License.
4  */
5 
6 /*!	\class KPPPConfigurePacket
7 	\brief Helper class for LCP configure packets.
8 
9 	This class allows iterating over configure items and adding/removing items.
10 */
11 
12 #include <ByteOrder.h>
13 #include <net_buffer.h>
14 #include <net_stack.h>
15 
16 #include <KPPPConfigurePacket.h>
17 #include <KPPPInterface.h>
18 
19 
20 /*!	\brief Constructor.
21 
22 	\param code The code value (e.g.: PPP_CONFIGURE_REQUEST) of this packet.
23 */
24 KPPPConfigurePacket::KPPPConfigurePacket(uint8 code)
25 	: fCode(code),
26 	fID(0)
27 {
28 }
29 
30 
31 //!	Decodes a packet and adds its items to this object.
32 KPPPConfigurePacket::KPPPConfigurePacket(net_buffer *packet)
33 {
34 	// decode packet
35 	NetBufferHeaderReader<ppp_lcp_packet> bufferhead(packet);
36 	if (bufferhead.Status() != B_OK)
37 		return;
38 	ppp_lcp_packet &header = bufferhead.Data();
39 
40 	SetID(header.id);
41 	if (!SetCode(header.code))
42 		return;
43 
44 	uint16 length = ntohs(header.length);
45 
46 	if (length < 6 || length > packet->size)
47 		return;
48 			// there are no items (or one corrupted item)
49 
50 	int32 position = 0;
51 	ppp_configure_item *item;
52 
53 	while (position < length - 4) {
54 		item = (ppp_configure_item*) (header.data + position);
55 		if (item->length < 2)
56 			return;
57 				// found a corrupted item
58 
59 		position += item->length;
60 		AddItem(item);
61 	}
62 }
63 
64 
65 //!	Frees all items.
66 KPPPConfigurePacket::~KPPPConfigurePacket()
67 {
68 	for (int32 index = 0; index < CountItems(); index++)
69 		free(ItemAt(index));
70 }
71 
72 
73 //!	Sets the packet's code value (e.g.: PPP_CONFIGURE_REQUEST).
74 bool
75 KPPPConfigurePacket::SetCode(uint8 code)
76 {
77 	// only configure codes are allowed!
78 	if (code < PPP_CONFIGURE_REQUEST || code > PPP_CONFIGURE_REJECT)
79 		return false;
80 
81 	fCode = code;
82 
83 	return true;
84 }
85 
86 
87 /*!	\brief Adds a new configure item to this packet.
88 
89 	Make sure all values are correct because the item will be copied. If the item's
90 	length field is incorrect you will get bad results.
91 
92 	\param item The item.
93 	\param index Item's index. Adds after the last item if not specified or negative.
94 
95 	\return \c true if successful, \c false otherwise.
96 
97 	\sa ppp_configure_item
98 */
99 bool
100 KPPPConfigurePacket::AddItem(const ppp_configure_item *item, int32 index)
101 {
102 	if (!item || item->length < 2)
103 		return false;
104 
105 	ppp_configure_item *add = (ppp_configure_item*) malloc(item->length);
106 	memcpy(add, item, item->length);
107 
108 	bool status;
109 	if (index < 0)
110 		status = fItems.AddItem(add);
111 	else
112 		status = fItems.AddItem(add, index);
113 	if (!status) {
114 		free(add);
115 		return false;
116 	}
117 
118 	return true;
119 }
120 
121 
122 //!	Removes an item. The item \e must belong to this packet.
123 bool
124 KPPPConfigurePacket::RemoveItem(ppp_configure_item *item)
125 {
126 	if (!fItems.HasItem(item))
127 		return false;
128 
129 	fItems.RemoveItem(item);
130 	free(item);
131 
132 	return true;
133 }
134 
135 
136 //!	Returns the item at \a index or \c NULL.
137 ppp_configure_item*
138 KPPPConfigurePacket::ItemAt(int32 index) const
139 {
140 	ppp_configure_item *item = fItems.ItemAt(index);
141 
142 	if (item == fItems.GetDefaultItem())
143 		return NULL;
144 
145 	return item;
146 }
147 
148 
149 //!	Returns the item of a special \a type or \c NULL.
150 ppp_configure_item*
151 KPPPConfigurePacket::ItemWithType(uint8 type) const
152 {
153 	ppp_configure_item *item;
154 
155 	for (int32 index = 0; index < CountItems(); index++) {
156 		item = ItemAt(index);
157 		if (item && item->type == type)
158 			return item;
159 	}
160 
161 	return NULL;
162 }
163 
164 
165 /*!	\brief Converts this packet into an net_buffer structure.
166 
167 	ATTENTION: You are responsible for freeing this packet by calling \c m_freem()!
168 
169 	\param MRU The interface's maximum receive unit (MRU).
170 	\param reserve Number of bytes to reserve at the beginning of the packet.
171 
172 	\return The net_buffer structure or \c NULL on error (e.g.: too big for given MRU).
173 */
174 net_buffer*
175 KPPPConfigurePacket::ToNetBuffer(uint32 MRU)
176 {
177 	net_buffer *buffer = gBufferModule->create(256);
178 	if (buffer == NULL) {
179 		TRACE("%s::%s: gBufferModule->create fail\n", __FILE__, __func__);
180 		return(NULL);
181 	}
182 
183 	ppp_lcp_packet *header;
184 	status_t status = gBufferModule->append_size(buffer, 1492, (void **)&header);
185 	if (status != B_OK) {
186 		TRACE("%s::%s: gBufferModule->append_size\n", __FILE__, __func__);
187 		gBufferModule->free(buffer);
188 		return(NULL);
189 	}
190 
191 	header->code = Code();
192 	header->id = ID();
193 
194 	uint16 length = 0;
195 	ppp_configure_item *item;
196 
197 	for (int32 index = 0; index < CountItems(); index++) {
198 		item = ItemAt(index);
199 
200 		// make sure we have enough space left
201 		if (MRU - length < item->length) {
202 			gBufferModule->free(buffer);
203 			return NULL;
204 		}
205 
206 		memcpy(header->data + length, item, item->length);
207 		length += item->length;
208 	}
209 
210 	length += 4;
211 	header->length = htons(length);
212 
213 	status = gBufferModule->trim(buffer, length);
214 	if (status < B_OK) {
215 		dprintf("%s::%s: gBufferModule->trim\n", __FILE__, __func__);
216 		gBufferModule->free(buffer);
217 		return(NULL);
218 	}
219 
220 	return buffer;
221 }
222