xref: /haiku/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPConfigurePacket.cpp (revision db10640de90f7f9519ba2da9577b7c1af3c64f6b)
1 //-----------------------------------------------------------------------
2 //  This software is part of the OpenBeOS distribution and is covered
3 //  by the OpenBeOS license.
4 //
5 //  Copyright (c) 2003-2004 Waldemar Kornewald, Waldemar.Kornewald@web.de
6 //-----------------------------------------------------------------------
7 
8 /*!	\class KPPPConfigurePacket
9 	\brief Helper class for LCP configure packets.
10 
11 	This class allows iterating over configure items and adding/removing items.
12 */
13 
14 #include <KPPPConfigurePacket.h>
15 #include <KPPPInterface.h>
16 
17 #include <core_funcs.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(struct mbuf *packet)
33 {
34 	// decode packet
35 	ppp_lcp_packet *header = mtod(packet, ppp_lcp_packet*);
36 
37 	SetID(header->id);
38 	if(!SetCode(header->code))
39 		return;
40 
41 	uint16 length = ntohs(header->length);
42 
43 	if(length < 6 || length > packet->m_len)
44 		return;
45 			// there are no items (or one corrupted item)
46 
47 	int32 position = 0;
48 	ppp_configure_item *item;
49 
50 	while(position < length - 4) {
51 		item = (ppp_configure_item*) (header->data + position);
52 		if(item->length < 2)
53 			return;
54 				// found a corrupted item
55 
56 		position += item->length;
57 		AddItem(item);
58 	}
59 }
60 
61 
62 //!	Frees all items.
63 KPPPConfigurePacket::~KPPPConfigurePacket()
64 {
65 	for(int32 index = 0; index < CountItems(); index++)
66 		free(ItemAt(index));
67 }
68 
69 
70 //!	Sets the packet's code value (e.g.: PPP_CONFIGURE_REQUEST).
71 bool
72 KPPPConfigurePacket::SetCode(uint8 code)
73 {
74 	// only configure codes are allowed!
75 	if(code < PPP_CONFIGURE_REQUEST || code > PPP_CONFIGURE_REJECT)
76 		return false;
77 
78 	fCode = code;
79 
80 	return true;
81 }
82 
83 
84 /*!	\brief Adds a new configure item to this packet.
85 
86 	Make sure all values are correct because the item will be copied. If the item's
87 	length field is incorrect you will get bad results.
88 
89 	\param item The item.
90 	\param index Item's index. Adds after the last item if not specified or negative.
91 
92 	\return \c true if successful, \c false otherwise.
93 
94 	\sa ppp_configure_item
95 */
96 bool
97 KPPPConfigurePacket::AddItem(const ppp_configure_item *item, int32 index = -1)
98 {
99 	if(!item || item->length < 2)
100 		return false;
101 
102 	ppp_configure_item *add = (ppp_configure_item*) malloc(item->length);
103 	memcpy(add, item, item->length);
104 
105 	bool status;
106 	if(index < 0)
107 		status = fItems.AddItem(add);
108 	else
109 		status = fItems.AddItem(add, index);
110 	if(!status) {
111 		free(add);
112 		return false;
113 	}
114 
115 	return true;
116 }
117 
118 
119 //!	Removes an item. The item \e must belong to this packet.
120 bool
121 KPPPConfigurePacket::RemoveItem(ppp_configure_item *item)
122 {
123 	if(!fItems.HasItem(item))
124 		return false;
125 
126 	fItems.RemoveItem(item);
127 	free(item);
128 
129 	return true;
130 }
131 
132 
133 //!	Returns the item at \a index or \c NULL.
134 ppp_configure_item*
135 KPPPConfigurePacket::ItemAt(int32 index) const
136 {
137 	ppp_configure_item *item = fItems.ItemAt(index);
138 
139 	if(item == fItems.GetDefaultItem())
140 		return NULL;
141 
142 	return item;
143 }
144 
145 
146 //!	Returns the item of a special \a type or \c NULL.
147 ppp_configure_item*
148 KPPPConfigurePacket::ItemWithType(uint8 type) const
149 {
150 	ppp_configure_item *item;
151 
152 	for(int32 index = 0; index < CountItems(); index++) {
153 		item = ItemAt(index);
154 		if(item && item->type == type)
155 			return item;
156 	}
157 
158 	return NULL;
159 }
160 
161 
162 /*!	\brief Converts this packet into an mbuf structure.
163 
164 	ATTENTION: You are responsible for freeing this packet by calling \c m_freem()!
165 
166 	\param MRU The interface's maximum receive unit (MRU).
167 	\param reserve Number of bytes to reserve at the beginning of the packet.
168 
169 	\return The mbuf structure or \c NULL on error (e.g.: too big for given MRU).
170 */
171 struct mbuf*
172 KPPPConfigurePacket::ToMbuf(uint32 MRU, uint32 reserve = 0)
173 {
174 	struct mbuf *packet = m_gethdr(MT_DATA);
175 	packet->m_data += reserve;
176 
177 	ppp_lcp_packet *header = mtod(packet, ppp_lcp_packet*);
178 
179 	header->code = Code();
180 	header->id = ID();
181 
182 	uint16 length = 0;
183 	ppp_configure_item *item;
184 
185 	for(int32 index = 0; index < CountItems(); index++) {
186 		item = ItemAt(index);
187 
188 		// make sure we have enough space left
189 		if(MRU - length < item->length) {
190 			m_freem(packet);
191 			return NULL;
192 		}
193 
194 		memcpy(header->data + length, item, item->length);
195 		length += item->length;
196 	}
197 
198 	length += 4;
199 	header->length = htons(length);
200 	packet->m_pkthdr.len = packet->m_len = length;
201 
202 	return packet;
203 }
204