1 /*
2 * Copyright 2003-2007, Waldemar Kornewald <wkornew@gmx.net>
3 * Distributed under the terms of the MIT License.
4 */
5
6 #include "_KPPPMRUHandler.h"
7
8 #include <KPPPConfigurePacket.h>
9 #include <KPPPDevice.h>
10
11 #include <netinet/in.h>
12
13
14 static const uint8 kMRUType = 0x1;
15
16 typedef struct mru_item {
17 uint8 type;
18 uint8 length;
19 uint16 MRU;
20 } _PACKED mru_item;
21
22 status_t ParseRequestedItem(mru_item *item, KPPPInterface& interface);
23
24
_KPPPMRUHandler(KPPPInterface & interface)25 _KPPPMRUHandler::_KPPPMRUHandler(KPPPInterface& interface)
26 : KPPPOptionHandler("MRU Handler", kMRUType, interface, NULL)
27 {
28 Reset();
29 }
30
31
32 status_t
AddToRequest(KPPPConfigurePacket & request)33 _KPPPMRUHandler::AddToRequest(KPPPConfigurePacket& request)
34 {
35 if (!Interface().Device() || Interface().MRU() == 1500)
36 return B_OK;
37
38 // add MRU request
39 mru_item item;
40 item.type = kMRUType;
41 item.length = 4;
42 item.MRU = htons(fLocalMRU);
43 return request.AddItem((ppp_configure_item*) &item) ? B_OK : B_ERROR;
44 }
45
46
47 status_t
ParseNak(const KPPPConfigurePacket & nak)48 _KPPPMRUHandler::ParseNak(const KPPPConfigurePacket& nak)
49 {
50 mru_item *item = (mru_item*) nak.ItemWithType(kMRUType);
51 if (!item || item->length != 4)
52 return B_OK;
53
54 uint16 MRU = ntohs(item->MRU);
55 if (MRU < fLocalMRU)
56 fLocalMRU = MRU;
57
58 return B_OK;
59 }
60
61
62 status_t
ParseReject(const KPPPConfigurePacket & reject)63 _KPPPMRUHandler::ParseReject(const KPPPConfigurePacket& reject)
64 {
65 if (reject.ItemWithType(kMRUType))
66 return B_ERROR;
67
68 return B_OK;
69 }
70
71
72 status_t
ParseAck(const KPPPConfigurePacket & ack)73 _KPPPMRUHandler::ParseAck(const KPPPConfigurePacket& ack)
74 {
75 uint16 MRU = 1500;
76 mru_item *item = (mru_item*) ack.ItemWithType(kMRUType);
77
78 if (item)
79 MRU = ntohs(item->MRU);
80
81 if (MRU < Interface().MRU())
82 fLocalMRU = MRU;
83
84 return B_OK;
85 }
86
87
88 status_t
ParseRequest(const KPPPConfigurePacket & request,int32 index,KPPPConfigurePacket & nak,KPPPConfigurePacket & reject)89 _KPPPMRUHandler::ParseRequest(const KPPPConfigurePacket& request,
90 int32 index, KPPPConfigurePacket& nak, KPPPConfigurePacket& reject)
91 {
92 if (index == reject.CountItems())
93 return B_OK;
94
95 return ParseRequestedItem((mru_item*) request.ItemAt(index), Interface());
96
97 return B_OK;
98 }
99
100
101 status_t
SendingAck(const KPPPConfigurePacket & ack)102 _KPPPMRUHandler::SendingAck(const KPPPConfigurePacket& ack)
103 {
104 return ParseRequestedItem((mru_item*) ack.ItemWithType(kMRUType), Interface());
105 }
106
107
108 // this function contains code shared by ParseRequest and SendingAck
109 status_t
ParseRequestedItem(mru_item * item,KPPPInterface & interface)110 ParseRequestedItem(mru_item *item, KPPPInterface& interface)
111 {
112 uint16 MRU = 1500;
113
114 if (item) {
115 if (item->length != 4)
116 return B_ERROR;
117 // the request has a corrupted item
118
119 MRU = ntohs(item->MRU);
120 }
121
122 if (MRU < interface.MRU())
123 interface.SetMRU(MRU);
124
125 return B_OK;
126 }
127
128
129 void
Reset()130 _KPPPMRUHandler::Reset()
131 {
132 if (Interface().Device()) {
133 fLocalMRU = Interface().Device()->MTU() - 2;
134 Interface().SetMRU(fLocalMRU);
135 } else {
136 Interface().SetMRU(1500);
137 fLocalMRU = 1500;
138 }
139 }
140