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