xref: /haiku/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPConfigurePacket.cpp (revision d5cd5d63ff0ad395989db6cf4841a64d5b545d1d)
1 //----------------------------------------------------------------------
2 //  This software is part of the OpenBeOS distribution and is covered
3 //  by the OpenBeOS license.
4 //
5 //  Copyright (c) 2003 Waldemar Kornewald, Waldemar.Kornewald@web.de
6 //---------------------------------------------------------------------
7 
8 #include <KPPPConfigurePacket.h>
9 #include <KPPPInterface.h>
10 
11 #include <core_funcs.h>
12 
13 
14 PPPConfigurePacket::PPPConfigurePacket(uint8 code)
15 	: fCode(code),
16 	fID(0)
17 {
18 }
19 
20 
21 PPPConfigurePacket::PPPConfigurePacket(struct mbuf *packet)
22 {
23 	// decode packet
24 	ppp_lcp_packet *header = mtod(packet, ppp_lcp_packet*);
25 
26 	SetID(header->id);
27 	if(!SetCode(header->code))
28 		return;
29 
30 	uint16 length = ntohs(header->length);
31 
32 	if(length < 6 || length > packet->m_len)
33 		return;
34 			// there are no items (or one corrupted item)
35 
36 	int32 position = 0;
37 	ppp_configure_item *item;
38 
39 	while(position < length - 4) {
40 		item = (ppp_configure_item*) (header->data + position);
41 		if(item->length < 2)
42 			return;
43 				// found a corrupted item
44 
45 		position += item->length;
46 		AddItem(item);
47 	}
48 }
49 
50 
51 PPPConfigurePacket::~PPPConfigurePacket()
52 {
53 	for(int32 index = 0; index < CountItems(); index++)
54 		free(ItemAt(index));
55 }
56 
57 
58 bool
59 PPPConfigurePacket::SetCode(uint8 code)
60 {
61 	// only configure codes are allowed!
62 	if(code < PPP_CONFIGURE_REQUEST || code > PPP_CONFIGURE_REJECT)
63 		return false;
64 
65 	fCode = code;
66 
67 	return true;
68 }
69 
70 
71 bool
72 PPPConfigurePacket::AddItem(const ppp_configure_item *item, int32 index = -1)
73 {
74 	if(!item || item->length < 2)
75 		return false;
76 
77 	ppp_configure_item *add = (ppp_configure_item*) malloc(item->length);
78 	memcpy(add, item, item->length);
79 
80 	bool status;
81 	if(index < 0)
82 		status = fItems.AddItem(add);
83 	else
84 		status = fItems.AddItem(add, index);
85 	if(!status) {
86 		free(add);
87 		return false;
88 	}
89 
90 	return true;
91 }
92 
93 
94 bool
95 PPPConfigurePacket::RemoveItem(ppp_configure_item *item)
96 {
97 	if(!fItems.HasItem(item))
98 		return false;
99 
100 	fItems.RemoveItem(item);
101 	free(item);
102 
103 	return true;
104 }
105 
106 
107 ppp_configure_item*
108 PPPConfigurePacket::ItemAt(int32 index) const
109 {
110 	ppp_configure_item *item = fItems.ItemAt(index);
111 
112 	if(item == fItems.GetDefaultItem())
113 		return NULL;
114 
115 	return item;
116 }
117 
118 
119 ppp_configure_item*
120 PPPConfigurePacket::ItemWithType(uint8 type) const
121 {
122 	ppp_configure_item *item;
123 
124 	for(int32 index = 0; index < CountItems(); index++) {
125 		item = ItemAt(index);
126 		if(item && item->type == type)
127 			return item;
128 	}
129 
130 	return NULL;
131 }
132 
133 
134 struct mbuf*
135 PPPConfigurePacket::ToMbuf(uint32 MRU, uint32 reserve = 0)
136 {
137 	struct mbuf *packet = m_gethdr(MT_DATA);
138 	packet->m_data += reserve;
139 
140 	ppp_lcp_packet *header = mtod(packet, ppp_lcp_packet*);
141 
142 	header->code = Code();
143 	header->id = ID();
144 
145 	uint16 length = 0;
146 	ppp_configure_item *item;
147 
148 	for(int32 index = 0; index < CountItems(); index++) {
149 		item = ItemAt(index);
150 
151 		// make sure we have enough space left
152 		if(MRU - length < item->length) {
153 			m_freem(packet);
154 			return NULL;
155 		}
156 
157 		memcpy(header->data + length, item, item->length);
158 		length += item->length;
159 	}
160 
161 	length += 4;
162 	header->length = htons(length);
163 	packet->m_pkthdr.len = packet->m_len = length;
164 
165 	return packet;
166 }
167