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