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
14static const uint8 kMRUType = 0x1;
15
16typedef struct mru_item {
17	uint8 type;
18	uint8 length;
19	uint16 MRU;
20} _PACKED mru_item;
21
22status_t ParseRequestedItem(mru_item *item, KPPPInterface& interface);
23
24
25_KPPPMRUHandler::_KPPPMRUHandler(KPPPInterface& interface)
26	: KPPPOptionHandler("MRU Handler", kMRUType, interface, NULL)
27{
28	Reset();
29}
30
31
32status_t
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
47status_t
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
62status_t
63_KPPPMRUHandler::ParseReject(const KPPPConfigurePacket& reject)
64{
65	if (reject.ItemWithType(kMRUType))
66		return B_ERROR;
67
68	return B_OK;
69}
70
71
72status_t
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
88status_t
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
101status_t
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
109status_t
110ParseRequestedItem(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
129void
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