Protocol.cpp revision cdee6f97
16cfb4dcaSWaldemar Kornewald//-----------------------------------------------------------------------
2ca43389aSWaldemar Kornewald//  This software is part of the OpenBeOS distribution and is covered
3ca43389aSWaldemar Kornewald//  by the OpenBeOS license.
4ca43389aSWaldemar Kornewald//
56cfb4dcaSWaldemar Kornewald//  Copyright (c) 2003-2004 Waldemar Kornewald, Waldemar.Kornewald@web.de
66cfb4dcaSWaldemar Kornewald//-----------------------------------------------------------------------
7ca43389aSWaldemar Kornewald
8cdee6f97SWaldemar Kornewald#if DEBUG
9cdee6f97SWaldemar Kornewald#include <cstdio>
10cdee6f97SWaldemar Kornewald#endif
11cdee6f97SWaldemar Kornewald
12ca43389aSWaldemar Kornewald#include "Protocol.h"
13b8f24e83SWaldemar Kornewald#include "IPCP.h"
14ca43389aSWaldemar Kornewald#include <KPPPConfigurePacket.h>
15ca43389aSWaldemar Kornewald#include <KPPPInterface.h>
161cea3d85SWaldemar Kornewald#include <settings_tools.h>
17ca43389aSWaldemar Kornewald
18ca43389aSWaldemar Kornewald#include <LockerHelper.h>
19ca43389aSWaldemar Kornewald
20ca43389aSWaldemar Kornewald#include <cstring>
2193a59056SWaldemar Kornewald#include <netinet/in_var.h>
22ca43389aSWaldemar Kornewald#include <core_funcs.h>
23ca43389aSWaldemar Kornewald#include <sys/sockio.h>
24ca43389aSWaldemar Kornewald
25ca43389aSWaldemar Kornewald
26cdee6f97SWaldemar Kornewald#if DEBUG
27cdee6f97SWaldemar Kornewald#include <unistd.h>
28cdee6f97SWaldemar Kornewald
29cdee6f97SWaldemar Kornewaldstatic int sFD;
30cdee6f97SWaldemar Kornewald	// the file descriptor for debug output
31cdee6f97SWaldemar Kornewaldstatic char sDigits[] = "0123456789ABCDEF";
32cdee6f97SWaldemar Kornewaldvoid
33cdee6f97SWaldemar Kornewalddump_packet(struct mbuf *packet, const char *direction)
34cdee6f97SWaldemar Kornewald{
35cdee6f97SWaldemar Kornewald	if(!packet)
36cdee6f97SWaldemar Kornewald		return;
37cdee6f97SWaldemar Kornewald
38cdee6f97SWaldemar Kornewald	uint8 *data = mtod(packet, uint8*);
39cdee6f97SWaldemar Kornewald	uint8 buffer[128];
40cdee6f97SWaldemar Kornewald	uint8 bufferIndex = 0;
41cdee6f97SWaldemar Kornewald
42cdee6f97SWaldemar Kornewald	sprintf((char*) buffer, "Dumping %s packet;len=%ld;pkthdr.len=%d\n", direction,
43cdee6f97SWaldemar Kornewald		packet->m_len, packet->m_flags & M_PKTHDR ? packet->m_pkthdr.len : -1);
44cdee6f97SWaldemar Kornewald	write(sFD, buffer, strlen((char*) buffer));
45cdee6f97SWaldemar Kornewald
46cdee6f97SWaldemar Kornewald	for(uint32 index = 0; index < packet->m_len; index++) {
47cdee6f97SWaldemar Kornewald		buffer[bufferIndex++] = sDigits[data[index] >> 4];
48cdee6f97SWaldemar Kornewald		buffer[bufferIndex++] = sDigits[data[index] & 0x0F];
49cdee6f97SWaldemar Kornewald		if(bufferIndex == 32 || index == packet->m_len - 1) {
50cdee6f97SWaldemar Kornewald			buffer[bufferIndex++] = '\n';
51cdee6f97SWaldemar Kornewald			buffer[bufferIndex] = 0;
52cdee6f97SWaldemar Kornewald			write(sFD, buffer, strlen((char*) buffer));
53cdee6f97SWaldemar Kornewald			bufferIndex = 0;
54cdee6f97SWaldemar Kornewald		}
55cdee6f97SWaldemar Kornewald	}
56cdee6f97SWaldemar Kornewald}
57cdee6f97SWaldemar Kornewald#endif
58cdee6f97SWaldemar Kornewald
59cdee6f97SWaldemar Kornewald
606ff76cdaSWaldemar Kornewaldstatic const bigtime_t kIPCPStateMachineTimeout = 3000000;
61ca43389aSWaldemar Kornewald	// 3 seconds
62ca43389aSWaldemar Kornewald
63ca43389aSWaldemar Kornewald
641cea3d85SWaldemar KornewaldIPCP::IPCP(KPPPInterface& interface, driver_parameter *settings)
651cea3d85SWaldemar Kornewald	: KPPPProtocol("IPCP", PPP_NCP_PHASE, IPCP_PROTOCOL, PPP_PROTOCOL_LEVEL,
66ca43389aSWaldemar Kornewald		AF_INET, 0, interface, settings, PPP_INCLUDES_NCP),
676cfb4dcaSWaldemar Kornewald	fDefaultRoute(NULL),
68ca43389aSWaldemar Kornewald	fRequestPrimaryDNS(false),
69ca43389aSWaldemar Kornewald	fRequestSecondaryDNS(false),
70ca43389aSWaldemar Kornewald	fState(PPP_INITIAL_STATE),
71ca43389aSWaldemar Kornewald	fID(system_time() & 0xFF),
72ca43389aSWaldemar Kornewald	fMaxRequest(10),
73ca43389aSWaldemar Kornewald	fMaxTerminate(2),
74ca43389aSWaldemar Kornewald	fMaxNak(5),
75ca43389aSWaldemar Kornewald	fRequestID(0),
76ca43389aSWaldemar Kornewald	fTerminateID(0),
77ca43389aSWaldemar Kornewald	fNextTimeout(0)
78ca43389aSWaldemar Kornewald{
79abf44d1aSWaldemar Kornewald	ProfileChanged();
80cdee6f97SWaldemar Kornewald
81cdee6f97SWaldemar Kornewald#if DEBUG
82cdee6f97SWaldemar Kornewald	sFD = open("/boot/home/ipcpdebug", O_WRONLY | O_CREAT | O_TRUNC);
83cdee6f97SWaldemar Kornewald#endif
84ca43389aSWaldemar Kornewald}
85ca43389aSWaldemar Kornewald
86ca43389aSWaldemar Kornewald
87ca43389aSWaldemar KornewaldIPCP::~IPCP()
88ce0b86e9SWaldemar Kornewald{
89cdee6f97SWaldemar Kornewald#if DEBUG
90cdee6f97SWaldemar Kornewald	close(sFD);
91cdee6f97SWaldemar Kornewald#endif
92ce0b86e9SWaldemar Kornewald}
93ce0b86e9SWaldemar Kornewald
94ce0b86e9SWaldemar Kornewald
95ce0b86e9SWaldemar Kornewaldvoid
96ce0b86e9SWaldemar KornewaldIPCP::Uninit()
97ca43389aSWaldemar Kornewald{
986cfb4dcaSWaldemar Kornewald	RemoveRoutes();
99ca43389aSWaldemar Kornewald}
100ca43389aSWaldemar Kornewald
101ca43389aSWaldemar Kornewald
10293a59056SWaldemar Kornewaldstatus_t
10393a59056SWaldemar KornewaldIPCP::StackControl(uint32 op, void *data)
10493a59056SWaldemar Kornewald{
10593a59056SWaldemar Kornewald#if DEBUG
1066cfb4dcaSWaldemar Kornewald	dprintf("IPCP: StackControl(op=%ld)\n", op);
10793a59056SWaldemar Kornewald#endif
10893a59056SWaldemar Kornewald
10993a59056SWaldemar Kornewald	// TODO:
11093a59056SWaldemar Kornewald	// check values
11193a59056SWaldemar Kornewald
11293a59056SWaldemar Kornewald	switch(op) {
11393a59056SWaldemar Kornewald		case SIOCSIFADDR:
11493a59056SWaldemar Kornewald		break;
11593a59056SWaldemar Kornewald
11693a59056SWaldemar Kornewald		case SIOCSIFFLAGS:
11793a59056SWaldemar Kornewald		break;
11893a59056SWaldemar Kornewald
11993a59056SWaldemar Kornewald		case SIOCSIFDSTADDR:
12093a59056SWaldemar Kornewald		break;
12193a59056SWaldemar Kornewald
12293a59056SWaldemar Kornewald		case SIOCSIFNETMASK:
12393a59056SWaldemar Kornewald		break;
12493a59056SWaldemar Kornewald
12593a59056SWaldemar Kornewald		default:
1266cfb4dcaSWaldemar Kornewald			dprintf("IPCP: Unknown ioctl: %ld\n", op);
1271cea3d85SWaldemar Kornewald			return KPPPProtocol::StackControl(op, data);
12893a59056SWaldemar Kornewald	}
12993a59056SWaldemar Kornewald
13093a59056SWaldemar Kornewald	return B_OK;
13193a59056SWaldemar Kornewald}
13293a59056SWaldemar Kornewald
13393a59056SWaldemar Kornewald
134abf44d1aSWaldemar Kornewaldvoid
135abf44d1aSWaldemar KornewaldIPCP::ProfileChanged()
136abf44d1aSWaldemar Kornewald{
137abf44d1aSWaldemar Kornewald	// reset configurations
138abf44d1aSWaldemar Kornewald	memset(&fLocalConfiguration, 0, sizeof(ipcp_configuration));
139abf44d1aSWaldemar Kornewald	memset(&fPeerConfiguration, 0, sizeof(ipcp_configuration));
140abf44d1aSWaldemar Kornewald
141abf44d1aSWaldemar Kornewald	// reset requests
142abf44d1aSWaldemar Kornewald	memset(&fLocalRequests, 0, sizeof(ipcp_requests));
143abf44d1aSWaldemar Kornewald	memset(&fPeerRequests, 0, sizeof(ipcp_requests));
144abf44d1aSWaldemar Kornewald
145abf44d1aSWaldemar Kornewald	// Parse settings:
146abf44d1aSWaldemar Kornewald	// "Local" and "Peer" describe each side's settings
147abf44d1aSWaldemar Kornewald	const driver_parameter *profile
148abf44d1aSWaldemar Kornewald		= Interface().Profile().SettingsFor("protocol", "ipcp");
149b8f24e83SWaldemar Kornewald	ParseSideRequests(get_parameter_with_name(IPCP_LOCAL_SIDE_KEY, profile),
150b8f24e83SWaldemar Kornewald		PPP_LOCAL_SIDE);
151b8f24e83SWaldemar Kornewald	ParseSideRequests(get_parameter_with_name(IPCP_PEER_SIDE_KEY, profile),
152b8f24e83SWaldemar Kornewald		PPP_PEER_SIDE);
153abf44d1aSWaldemar Kornewald}
154abf44d1aSWaldemar Kornewald
155abf44d1aSWaldemar Kornewald
156ca43389aSWaldemar Kornewaldbool
157ca43389aSWaldemar KornewaldIPCP::Up()
158ca43389aSWaldemar Kornewald{
159ca43389aSWaldemar Kornewald#if DEBUG
1606cfb4dcaSWaldemar Kornewald	dprintf("IPCP: Up() state=%d\n", State());
161ca43389aSWaldemar Kornewald#endif
162ca43389aSWaldemar Kornewald
163ca43389aSWaldemar Kornewald	// Servers do not send a configure-request when Up() is called. They wait until
164ca43389aSWaldemar Kornewald	// the client requests this protocol.
165ca43389aSWaldemar Kornewald	if(Interface().Mode() == PPP_SERVER_MODE)
166ca43389aSWaldemar Kornewald		return true;
167ca43389aSWaldemar Kornewald
168ca43389aSWaldemar Kornewald	LockerHelper locker(fLock);
169ca43389aSWaldemar Kornewald
170ca43389aSWaldemar Kornewald	switch(State()) {
171ca43389aSWaldemar Kornewald		case PPP_INITIAL_STATE:
172ca43389aSWaldemar Kornewald			NewState(PPP_REQ_SENT_STATE);
173ca43389aSWaldemar Kornewald			InitializeRestartCount();
174ca43389aSWaldemar Kornewald			locker.UnlockNow();
175ca43389aSWaldemar Kornewald			SendConfigureRequest();
176ca43389aSWaldemar Kornewald		break;
177ca43389aSWaldemar Kornewald
178ca43389aSWaldemar Kornewald		default:
179ca43389aSWaldemar Kornewald			;
180ca43389aSWaldemar Kornewald	}
181ca43389aSWaldemar Kornewald
182ca43389aSWaldemar Kornewald	return true;
183ca43389aSWaldemar Kornewald}
184ca43389aSWaldemar Kornewald
185ca43389aSWaldemar Kornewald
186ca43389aSWaldemar Kornewaldbool
187ca43389aSWaldemar KornewaldIPCP::Down()
188ca43389aSWaldemar Kornewald{
189ca43389aSWaldemar Kornewald#if DEBUG
1906cfb4dcaSWaldemar Kornewald	dprintf("IPCP: Down() state=%d\n", State());
191ca43389aSWaldemar Kornewald#endif
192ca43389aSWaldemar Kornewald
193ca43389aSWaldemar Kornewald	LockerHelper locker(fLock);
194ca43389aSWaldemar Kornewald
195ca43389aSWaldemar Kornewald	switch(Interface().Phase()) {
196ca43389aSWaldemar Kornewald		case PPP_DOWN_PHASE:
197ca43389aSWaldemar Kornewald			// interface finished terminating
198ca43389aSWaldemar Kornewald			NewState(PPP_INITIAL_STATE);
199ca43389aSWaldemar Kornewald			locker.UnlockNow();
200ca43389aSWaldemar Kornewald			ReportDownEvent();
201ca43389aSWaldemar Kornewald				// this will also reset and update addresses
202ca43389aSWaldemar Kornewald		break;
203ca43389aSWaldemar Kornewald
204ca43389aSWaldemar Kornewald/*		case PPP_TERMINATION_PHASE:
205ca43389aSWaldemar Kornewald			// interface is terminating
206ca43389aSWaldemar Kornewald		break;
207ca43389aSWaldemar Kornewald
208ca43389aSWaldemar Kornewald		case PPP_ESTABLISHMENT_PHASE:
209ca43389aSWaldemar Kornewald			// interface is reconfiguring
210ca43389aSWaldemar Kornewald		break;
211ca43389aSWaldemar Kornewald*/
212ca43389aSWaldemar Kornewald		case PPP_ESTABLISHED_PHASE:
213ca43389aSWaldemar Kornewald			// terminate this NCP individually (block until we finished terminating)
214ca43389aSWaldemar Kornewald			if(State() != PPP_INITIAL_STATE && State() != PPP_CLOSING_STATE) {
215ca43389aSWaldemar Kornewald				NewState(PPP_CLOSING_STATE);
216ca43389aSWaldemar Kornewald				InitializeRestartCount();
217ca43389aSWaldemar Kornewald				locker.UnlockNow();
218ca43389aSWaldemar Kornewald				SendTerminateRequest();
219ca43389aSWaldemar Kornewald			}
220ca43389aSWaldemar Kornewald
221ca43389aSWaldemar Kornewald			while(State() == PPP_CLOSING_STATE)
222ca43389aSWaldemar Kornewald				snooze(50000);
223ca43389aSWaldemar Kornewald		break;
224ca43389aSWaldemar Kornewald
225ca43389aSWaldemar Kornewald		default:
226ca43389aSWaldemar Kornewald			;
227ca43389aSWaldemar Kornewald	}
228ca43389aSWaldemar Kornewald
229ca43389aSWaldemar Kornewald	return true;
230ca43389aSWaldemar Kornewald}
231ca43389aSWaldemar Kornewald
232ca43389aSWaldemar Kornewald
233ca43389aSWaldemar Kornewaldstatus_t
234ca43389aSWaldemar KornewaldIPCP::Send(struct mbuf *packet, uint16 protocolNumber = IPCP_PROTOCOL)
235ca43389aSWaldemar Kornewald{
23686c13ddaSWaldemar Kornewald#if DEBUG
2376cfb4dcaSWaldemar Kornewald	dprintf("IPCP: Send(0x%X)\n", protocolNumber);
23886c13ddaSWaldemar Kornewald#endif
23986c13ddaSWaldemar Kornewald
24093a59056SWaldemar Kornewald	if((protocolNumber == IP_PROTOCOL && State() == PPP_OPENED_STATE)
241cdee6f97SWaldemar Kornewald			|| protocolNumber == IPCP_PROTOCOL) {
242cdee6f97SWaldemar Kornewald#if DEBUG
243cdee6f97SWaldemar Kornewald		dump_packet(packet, "outgoing");
244cdee6f97SWaldemar Kornewald#endif
245cdee6f97SWaldemar Kornewald		Interface().UpdateIdleSince();
24693a59056SWaldemar Kornewald		return SendToNext(packet, protocolNumber);
247cdee6f97SWaldemar Kornewald	}
248ca43389aSWaldemar Kornewald
2496cfb4dcaSWaldemar Kornewald	dprintf("IPCP: Send() failed because of wrong state or protocol number!\n");
25086c13ddaSWaldemar Kornewald
25193a59056SWaldemar Kornewald	m_freem(packet);
25293a59056SWaldemar Kornewald	return B_ERROR;
253ca43389aSWaldemar Kornewald}
254ca43389aSWaldemar Kornewald
255ca43389aSWaldemar Kornewald
256ca43389aSWaldemar Kornewaldstatus_t
257ca43389aSWaldemar KornewaldIPCP::Receive(struct mbuf *packet, uint16 protocolNumber)
258ca43389aSWaldemar Kornewald{
25986c13ddaSWaldemar Kornewald#if DEBUG
2606cfb4dcaSWaldemar Kornewald	dprintf("IPCP: Receive(0x%X)\n", protocolNumber);
26186c13ddaSWaldemar Kornewald#endif
26286c13ddaSWaldemar Kornewald
263ca43389aSWaldemar Kornewald	if(!packet)
264ca43389aSWaldemar Kornewald		return B_ERROR;
265ca43389aSWaldemar Kornewald
2668dad9b1eSWaldemar Kornewald	if(protocolNumber == IP_PROTOCOL)
2678dad9b1eSWaldemar Kornewald		return ReceiveIPPacket(packet, protocolNumber);
2688dad9b1eSWaldemar Kornewald
269ca43389aSWaldemar Kornewald	if(protocolNumber != IPCP_PROTOCOL)
270ca43389aSWaldemar Kornewald		return PPP_UNHANDLED;
271ca43389aSWaldemar Kornewald
272ca43389aSWaldemar Kornewald	ppp_lcp_packet *data = mtod(packet, ppp_lcp_packet*);
273ca43389aSWaldemar Kornewald
274ca43389aSWaldemar Kornewald	// remove padding
275ca43389aSWaldemar Kornewald	int32 length = packet->m_len;
276ca43389aSWaldemar Kornewald	if(packet->m_flags & M_PKTHDR)
277ca43389aSWaldemar Kornewald		length = packet->m_pkthdr.len;
278ca43389aSWaldemar Kornewald	length -= ntohs(data->length);
279ca43389aSWaldemar Kornewald	if(length)
280ca43389aSWaldemar Kornewald		m_adj(packet, -length);
281ca43389aSWaldemar Kornewald
282ca43389aSWaldemar Kornewald	if(ntohs(data->length) < 4)
283ca43389aSWaldemar Kornewald		return B_ERROR;
284ca43389aSWaldemar Kornewald
285ca43389aSWaldemar Kornewald	// packet is freed by event methods
286ca43389aSWaldemar Kornewald	switch(data->code) {
287ca43389aSWaldemar Kornewald		case PPP_CONFIGURE_REQUEST:
288ca43389aSWaldemar Kornewald			RCREvent(packet);
289ca43389aSWaldemar Kornewald		break;
290ca43389aSWaldemar Kornewald
291ca43389aSWaldemar Kornewald		case PPP_CONFIGURE_ACK:
292ca43389aSWaldemar Kornewald			RCAEvent(packet);
293ca43389aSWaldemar Kornewald		break;
294ca43389aSWaldemar Kornewald
295ca43389aSWaldemar Kornewald		case PPP_CONFIGURE_NAK:
296ca43389aSWaldemar Kornewald		case PPP_CONFIGURE_REJECT:
297ca43389aSWaldemar Kornewald			RCNEvent(packet);
298ca43389aSWaldemar Kornewald		break;
299ca43389aSWaldemar Kornewald
300ca43389aSWaldemar Kornewald		case PPP_TERMINATE_REQUEST:
301ca43389aSWaldemar Kornewald			RTREvent(packet);
302ca43389aSWaldemar Kornewald		break;
303ca43389aSWaldemar Kornewald
304ca43389aSWaldemar Kornewald		case PPP_TERMINATE_ACK:
305ca43389aSWaldemar Kornewald			RTAEvent(packet);
306ca43389aSWaldemar Kornewald		break;
307ca43389aSWaldemar Kornewald
308ca43389aSWaldemar Kornewald		case PPP_CODE_REJECT:
309ca43389aSWaldemar Kornewald			RXJBadEvent(packet);
310ca43389aSWaldemar Kornewald				// we implemented the minimum requirements
311ca43389aSWaldemar Kornewald		break;
312ca43389aSWaldemar Kornewald
313ca43389aSWaldemar Kornewald		default:
314ca43389aSWaldemar Kornewald			RUCEvent(packet);
315ca43389aSWaldemar Kornewald			return PPP_REJECTED;
316ca43389aSWaldemar Kornewald	}
317ca43389aSWaldemar Kornewald
318ca43389aSWaldemar Kornewald	return B_OK;
319ca43389aSWaldemar Kornewald}
320ca43389aSWaldemar Kornewald
321ca43389aSWaldemar Kornewald
322ca43389aSWaldemar Kornewaldstatus_t
323ca43389aSWaldemar KornewaldIPCP::ReceiveIPPacket(struct mbuf *packet, uint16 protocolNumber)
324ca43389aSWaldemar Kornewald{
32593a59056SWaldemar Kornewald	if(protocolNumber != IP_PROTOCOL || State() != PPP_OPENED_STATE)
326ca43389aSWaldemar Kornewald		return PPP_UNHANDLED;
327ca43389aSWaldemar Kornewald
328ca43389aSWaldemar Kornewald	// TODO: add VJC support (the packet would be decoded here)
329ca43389aSWaldemar Kornewald
33093a59056SWaldemar Kornewald	if (gProto[IPPROTO_IP] && gProto[IPPROTO_IP]->pr_input) {
331cdee6f97SWaldemar Kornewald#if DEBUG
332cdee6f97SWaldemar Kornewald		dump_packet(packet, "incoming");
333cdee6f97SWaldemar Kornewald#endif
334cdee6f97SWaldemar Kornewald		Interface().UpdateIdleSince();
33593a59056SWaldemar Kornewald		gProto[IPPROTO_IP]->pr_input(packet, 0);
336ca43389aSWaldemar Kornewald		return B_OK;
337ca43389aSWaldemar Kornewald	} else {
3386cfb4dcaSWaldemar Kornewald		dprintf("IPCP: Error: Could not find input function for IP!\n");
339ca43389aSWaldemar Kornewald		m_freem(packet);
340ca43389aSWaldemar Kornewald		return B_ERROR;
341ca43389aSWaldemar Kornewald	}
342ca43389aSWaldemar Kornewald}
343ca43389aSWaldemar Kornewald
344ca43389aSWaldemar Kornewald
345ca43389aSWaldemar Kornewaldvoid
346ca43389aSWaldemar KornewaldIPCP::Pulse()
347ca43389aSWaldemar Kornewald{
348ca43389aSWaldemar Kornewald	LockerHelper locker(fLock);
349ca43389aSWaldemar Kornewald	if(fNextTimeout == 0 || fNextTimeout > system_time())
350ca43389aSWaldemar Kornewald		return;
351ca43389aSWaldemar Kornewald	fNextTimeout = 0;
352ca43389aSWaldemar Kornewald	locker.UnlockNow();
353ca43389aSWaldemar Kornewald
354ca43389aSWaldemar Kornewald	switch(State()) {
355ca43389aSWaldemar Kornewald		case PPP_CLOSING_STATE:
356ca43389aSWaldemar Kornewald			if(fTerminateCounter <= 0)
357ca43389aSWaldemar Kornewald				TOBadEvent();
358ca43389aSWaldemar Kornewald			else
359ca43389aSWaldemar Kornewald				TOGoodEvent();
360ca43389aSWaldemar Kornewald		break;
361ca43389aSWaldemar Kornewald
362ca43389aSWaldemar Kornewald		case PPP_REQ_SENT_STATE:
363ca43389aSWaldemar Kornewald		case PPP_ACK_RCVD_STATE:
364ca43389aSWaldemar Kornewald		case PPP_ACK_SENT_STATE:
365ca43389aSWaldemar Kornewald			if(fRequestCounter <= 0)
366ca43389aSWaldemar Kornewald				TOBadEvent();
367ca43389aSWaldemar Kornewald			else
368ca43389aSWaldemar Kornewald				TOGoodEvent();
369ca43389aSWaldemar Kornewald		break;
370ca43389aSWaldemar Kornewald
371ca43389aSWaldemar Kornewald		default:
372ca43389aSWaldemar Kornewald			;
373ca43389aSWaldemar Kornewald	}
374ca43389aSWaldemar Kornewald}
375ca43389aSWaldemar Kornewald
376ca43389aSWaldemar Kornewald
377ca43389aSWaldemar Kornewaldbool
3781cea3d85SWaldemar KornewaldIPCP::ParseSideRequests(const driver_parameter *requests, ppp_side side)
379ca43389aSWaldemar Kornewald{
3801cea3d85SWaldemar Kornewald	if(!requests)
3811cea3d85SWaldemar Kornewald		return false;
3821cea3d85SWaldemar Kornewald
383ca43389aSWaldemar Kornewald	ipcp_requests *selectedRequests;
384ca43389aSWaldemar Kornewald
385ca43389aSWaldemar Kornewald	if(side == PPP_LOCAL_SIDE) {
386ca43389aSWaldemar Kornewald		selectedRequests = &fLocalRequests;
387ca43389aSWaldemar Kornewald		fRequestPrimaryDNS = fRequestSecondaryDNS = false;
388ca43389aSWaldemar Kornewald	} else
389ca43389aSWaldemar Kornewald		selectedRequests = &fPeerRequests;
390ca43389aSWaldemar Kornewald
391ca43389aSWaldemar Kornewald	memset(selectedRequests, 0, sizeof(ipcp_requests));
392ca43389aSWaldemar Kornewald		// reset current requests
393ca43389aSWaldemar Kornewald
394ca43389aSWaldemar Kornewald	// The following values are allowed:
395ca43389aSWaldemar Kornewald	//  "Address"		the ip address that will be suggested
396ca43389aSWaldemar Kornewald	//  "Netmask"		the netmask that should be used
397ca43389aSWaldemar Kornewald	//  "PrimaryDNS"	primary DNS server
398ca43389aSWaldemar Kornewald	//  "SecondaryDNS"	secondary DNS server
399ca43389aSWaldemar Kornewald	// Setting any value to 0.0.0.0 or "auto" means it should be chosen automatically.
400ca43389aSWaldemar Kornewald
401ca43389aSWaldemar Kornewald	in_addr_t address = INADDR_ANY;
402ca43389aSWaldemar Kornewald	for(int32 index = 0; index < requests->parameter_count; index++) {
403ca43389aSWaldemar Kornewald		if(requests->parameters[index].value_count == 0)
404ca43389aSWaldemar Kornewald			continue;
405ca43389aSWaldemar Kornewald
406ca43389aSWaldemar Kornewald		// all values are IP addresses, so parse the address here
407ca43389aSWaldemar Kornewald		if(strcasecmp(requests->parameters[index].values[0], "auto")) {
408ca43389aSWaldemar Kornewald			address = inet_addr(requests->parameters[index].values[0]);
409ca43389aSWaldemar Kornewald			if(address == INADDR_NONE)
410ca43389aSWaldemar Kornewald				continue;
411ca43389aSWaldemar Kornewald		}
412ca43389aSWaldemar Kornewald
413b8f24e83SWaldemar Kornewald		if(!strcasecmp(requests->parameters[index].name, IPCP_IP_ADDRESS_KEY))
414ca43389aSWaldemar Kornewald			selectedRequests->address = address;
415b8f24e83SWaldemar Kornewald		else if(!strcasecmp(requests->parameters[index].name, IPCP_NETMASK_KEY))
416ca43389aSWaldemar Kornewald			selectedRequests->netmask = address;
417b8f24e83SWaldemar Kornewald		else if(!strcasecmp(requests->parameters[index].name, IPCP_PRIMARY_DNS_KEY)) {
418ca43389aSWaldemar Kornewald			selectedRequests->primaryDNS = address;
419ca43389aSWaldemar Kornewald			if(side == PPP_LOCAL_SIDE)
420ca43389aSWaldemar Kornewald				fRequestPrimaryDNS = true;
421b8f24e83SWaldemar Kornewald		} else if(!strcasecmp(requests->parameters[index].name,
422b8f24e83SWaldemar Kornewald				IPCP_SECONDARY_DNS_KEY)) {
423ca43389aSWaldemar Kornewald			selectedRequests->secondaryDNS = address;
424ca43389aSWaldemar Kornewald			if(side == PPP_LOCAL_SIDE)
425ca43389aSWaldemar Kornewald				fRequestSecondaryDNS = true;
426ca43389aSWaldemar Kornewald		}
427ca43389aSWaldemar Kornewald	}
428ca43389aSWaldemar Kornewald
429ca43389aSWaldemar Kornewald	return true;
430ca43389aSWaldemar Kornewald}
431ca43389aSWaldemar Kornewald
432ca43389aSWaldemar Kornewald
433ca43389aSWaldemar Kornewaldvoid
434ca43389aSWaldemar KornewaldIPCP::UpdateAddresses()
435ca43389aSWaldemar Kornewald{
4366cfb4dcaSWaldemar Kornewald	RemoveRoutes();
4376cfb4dcaSWaldemar Kornewald
43820d09e03SWaldemar Kornewald	if(State() != PPP_OPENED_STATE && !Interface().DoesDialOnDemand())
439ca43389aSWaldemar Kornewald		return;
440ca43389aSWaldemar Kornewald
44193a59056SWaldemar Kornewald	struct in_aliasreq inreq;
44293a59056SWaldemar Kornewald	struct ifreq ifreqAddress, ifreqDestination;
44386c13ddaSWaldemar Kornewald	memset(&inreq, 0, sizeof(struct in_aliasreq));
44486c13ddaSWaldemar Kornewald	memset(&ifreqAddress, 0, sizeof(struct ifreq));
44586c13ddaSWaldemar Kornewald	memset(&ifreqDestination, 0, sizeof(struct ifreq));
4466cfb4dcaSWaldemar Kornewald	memset(&fGateway, 0, sizeof(struct sockaddr_in));
44793a59056SWaldemar Kornewald
44886c13ddaSWaldemar Kornewald	// create local address
44993a59056SWaldemar Kornewald	inreq.ifra_addr.sin_family = AF_INET;
45093a59056SWaldemar Kornewald	if(fLocalRequests.address != INADDR_ANY)
45193a59056SWaldemar Kornewald		inreq.ifra_addr.sin_addr.s_addr = fLocalRequests.address;
45293a59056SWaldemar Kornewald	else if(fLocalConfiguration.address == INADDR_ANY)
45393a59056SWaldemar Kornewald		inreq.ifra_addr.sin_addr.s_addr = INADDR_BROADCAST;
45493a59056SWaldemar Kornewald	else
45593a59056SWaldemar Kornewald		inreq.ifra_addr.sin_addr.s_addr = fLocalConfiguration.address;
45686c13ddaSWaldemar Kornewald	inreq.ifra_addr.sin_len = sizeof(struct sockaddr_in);
45786c13ddaSWaldemar Kornewald	memcpy(&ifreqAddress.ifr_addr, &inreq.ifra_addr, sizeof(struct sockaddr_in));
45893a59056SWaldemar Kornewald
45986c13ddaSWaldemar Kornewald	// create destination address
4606cfb4dcaSWaldemar Kornewald	fGateway.sin_family = AF_INET;
46193a59056SWaldemar Kornewald	if(fPeerRequests.address != INADDR_ANY)
4626cfb4dcaSWaldemar Kornewald		fGateway.sin_addr.s_addr = fPeerRequests.address;
46393a59056SWaldemar Kornewald	else if(fPeerConfiguration.address == INADDR_ANY)
4646cfb4dcaSWaldemar Kornewald		fGateway.sin_addr.s_addr = INADDR_BROADCAST;
46593a59056SWaldemar Kornewald	else
4666cfb4dcaSWaldemar Kornewald		fGateway.sin_addr.s_addr = fPeerConfiguration.address;
4676cfb4dcaSWaldemar Kornewald	fGateway.sin_len = sizeof(struct sockaddr_in);
4686cfb4dcaSWaldemar Kornewald	memcpy(&inreq.ifra_dstaddr, &fGateway,
46986c13ddaSWaldemar Kornewald		sizeof(struct sockaddr_in));
47086c13ddaSWaldemar Kornewald	memcpy(&ifreqDestination.ifr_dstaddr, &inreq.ifra_dstaddr,
47186c13ddaSWaldemar Kornewald		sizeof(struct sockaddr_in));
47286c13ddaSWaldemar Kornewald
47386c13ddaSWaldemar Kornewald	// create netmask
47493a59056SWaldemar Kornewald	inreq.ifra_mask.sin_family = AF_INET;
47586c13ddaSWaldemar Kornewald	inreq.ifra_mask.sin_addr.s_addr = fLocalRequests.netmask;
47686c13ddaSWaldemar Kornewald	inreq.ifra_mask.sin_len = sizeof(struct sockaddr_in);
47793a59056SWaldemar Kornewald
47886c13ddaSWaldemar Kornewald	// tell stack to use these values
47986c13ddaSWaldemar Kornewald	if(in_control(NULL, SIOCAIFADDR, (caddr_t) &inreq,
48086c13ddaSWaldemar Kornewald			Interface().Ifnet()) != B_OK)
4816cfb4dcaSWaldemar Kornewald		dprintf("IPCP: UpdateAddress(): SIOCAIFADDR returned error!\n");
48293a59056SWaldemar Kornewald	if(in_control(NULL, SIOCSIFADDR, (caddr_t) &ifreqAddress,
48393a59056SWaldemar Kornewald			Interface().Ifnet()) != B_OK)
4846cfb4dcaSWaldemar Kornewald		dprintf("IPCP: UpdateAddress(): SIOCSIFADDR returned error!\n");
48593a59056SWaldemar Kornewald	if(in_control(NULL, SIOCSIFDSTADDR, (caddr_t) &ifreqDestination,
48693a59056SWaldemar Kornewald			Interface().Ifnet()) != B_OK)
4876cfb4dcaSWaldemar Kornewald		dprintf("IPCP: UpdateAddress(): SIOCSIFDSTADDR returned error!\n");
48886c13ddaSWaldemar Kornewald	memcpy(&inreq.ifra_addr, &inreq.ifra_mask, sizeof(struct sockaddr_in));
48986c13ddaSWaldemar Kornewald		// SIOCISFNETMASK wants the netmask to be in ifra_addr
49086c13ddaSWaldemar Kornewald	if(in_control(NULL, SIOCSIFNETMASK, (caddr_t) &inreq,
49186c13ddaSWaldemar Kornewald			Interface().Ifnet()) != B_OK)
4926cfb4dcaSWaldemar Kornewald		dprintf("IPCP: UpdateAddress(): SIOCSIFNETMASK returned error!\n");
49386c13ddaSWaldemar Kornewald
49486c13ddaSWaldemar Kornewald	// add default/subnet route
4951cea3d85SWaldemar Kornewald	if(Side() == PPP_LOCAL_SIDE) {
4961cea3d85SWaldemar Kornewald		if(rtrequest(RTM_ADD, (struct sockaddr*) &inreq.ifra_mask,
4971cea3d85SWaldemar Kornewald				(struct sockaddr*) &fGateway, (struct sockaddr*) &inreq.ifra_mask,
4981cea3d85SWaldemar Kornewald				RTF_UP | RTF_GATEWAY, &fDefaultRoute) != B_OK)
4991cea3d85SWaldemar Kornewald			dprintf("IPCP: UpdateAddress(): could not add default/subnet route!\n");
5001cea3d85SWaldemar Kornewald
5011cea3d85SWaldemar Kornewald		--fDefaultRoute->rt_refcnt;
5021cea3d85SWaldemar Kornewald	}
5036cfb4dcaSWaldemar Kornewald}
5046cfb4dcaSWaldemar Kornewald
5056cfb4dcaSWaldemar Kornewald
5066cfb4dcaSWaldemar Kornewaldvoid
5076cfb4dcaSWaldemar KornewaldIPCP::RemoveRoutes()
5086cfb4dcaSWaldemar Kornewald{
5096cfb4dcaSWaldemar Kornewald	// note: netstack creates and deletes destination route automatically
51086c13ddaSWaldemar Kornewald
5116cfb4dcaSWaldemar Kornewald	if(fDefaultRoute) {
5126cfb4dcaSWaldemar Kornewald		struct sockaddr_in netmask;
5136cfb4dcaSWaldemar Kornewald		memset(&netmask, 0, sizeof(struct sockaddr_in));
5146cfb4dcaSWaldemar Kornewald
5156cfb4dcaSWaldemar Kornewald		netmask.sin_family = AF_INET;
5166cfb4dcaSWaldemar Kornewald		netmask.sin_addr.s_addr = fLocalRequests.netmask;
5176cfb4dcaSWaldemar Kornewald		netmask.sin_len = sizeof(struct sockaddr_in);
5186cfb4dcaSWaldemar Kornewald
5196cfb4dcaSWaldemar Kornewald		if(rtrequest(RTM_DELETE, (struct sockaddr*) &netmask,
5206cfb4dcaSWaldemar Kornewald				(struct sockaddr*) &fGateway, (struct sockaddr*) &netmask,
521ce0b86e9SWaldemar Kornewald				RTF_UP | RTF_GATEWAY, &fDefaultRoute) != B_OK)
5226cfb4dcaSWaldemar Kornewald			dprintf("IPCP: RemoveRoutes(): could not remove default/subnet route!\n");
5236cfb4dcaSWaldemar Kornewald
5246cfb4dcaSWaldemar Kornewald		fDefaultRoute = NULL;
5256cfb4dcaSWaldemar Kornewald	}
526ca43389aSWaldemar Kornewald}
527ca43389aSWaldemar Kornewald
528ca43389aSWaldemar Kornewald
529ca43389aSWaldemar Kornewalduint8
530ca43389aSWaldemar KornewaldIPCP::NextID()
531ca43389aSWaldemar Kornewald{
532ca43389aSWaldemar Kornewald	return (uint8) atomic_add(&fID, 1);
533ca43389aSWaldemar Kornewald}
534ca43389aSWaldemar Kornewald
535ca43389aSWaldemar Kornewald
536ca43389aSWaldemar Kornewaldvoid
537ca43389aSWaldemar KornewaldIPCP::NewState(ppp_state next)
538ca43389aSWaldemar Kornewald{
539ca43389aSWaldemar Kornewald#if DEBUG
5406cfb4dcaSWaldemar Kornewald	dprintf("IPCP: NewState(%d) state=%d\n", next, State());
541ca43389aSWaldemar Kornewald#endif
542ca43389aSWaldemar Kornewald
543ca43389aSWaldemar Kornewald	// report state changes
544ca43389aSWaldemar Kornewald	if(State() == PPP_INITIAL_STATE && next != State())
545ca43389aSWaldemar Kornewald		UpStarted();
546ca43389aSWaldemar Kornewald	else if(State() == PPP_OPENED_STATE && next != State())
547ca43389aSWaldemar Kornewald		DownStarted();
548ca43389aSWaldemar Kornewald
549ca43389aSWaldemar Kornewald	// maybe we do not need the timer anymore
550ca43389aSWaldemar Kornewald	if(next < PPP_CLOSING_STATE || next == PPP_OPENED_STATE)
551ca43389aSWaldemar Kornewald		fNextTimeout = 0;
552ca43389aSWaldemar Kornewald
553ca43389aSWaldemar Kornewald	fState = next;
554ca43389aSWaldemar Kornewald}
555ca43389aSWaldemar Kornewald
556ca43389aSWaldemar Kornewald
557ca43389aSWaldemar Kornewaldvoid
558ca43389aSWaldemar KornewaldIPCP::TOGoodEvent()
559ca43389aSWaldemar Kornewald{
560ca43389aSWaldemar Kornewald#if DEBUG
5616cfb4dcaSWaldemar Kornewald	dprintf("IPCP: TOGoodEvent() state=%d\n", State());
562ca43389aSWaldemar Kornewald#endif
563ca43389aSWaldemar Kornewald
564ca43389aSWaldemar Kornewald	LockerHelper locker(fLock);
565ca43389aSWaldemar Kornewald
566ca43389aSWaldemar Kornewald	switch(State()) {
567ca43389aSWaldemar Kornewald		case PPP_CLOSING_STATE:
568ca43389aSWaldemar Kornewald			locker.UnlockNow();
569ca43389aSWaldemar Kornewald			SendTerminateRequest();
570ca43389aSWaldemar Kornewald		break;
571ca43389aSWaldemar Kornewald
572ca43389aSWaldemar Kornewald		case PPP_ACK_RCVD_STATE:
573ca43389aSWaldemar Kornewald			NewState(PPP_REQ_SENT_STATE);
574ca43389aSWaldemar Kornewald
575ca43389aSWaldemar Kornewald		case PPP_REQ_SENT_STATE:
576ca43389aSWaldemar Kornewald		case PPP_ACK_SENT_STATE:
577ca43389aSWaldemar Kornewald			locker.UnlockNow();
578ca43389aSWaldemar Kornewald			SendConfigureRequest();
579ca43389aSWaldemar Kornewald		break;
580ca43389aSWaldemar Kornewald
581ca43389aSWaldemar Kornewald		default:
582ca43389aSWaldemar Kornewald			IllegalEvent(PPP_TO_GOOD_EVENT);
583ca43389aSWaldemar Kornewald	}
584ca43389aSWaldemar Kornewald}
585ca43389aSWaldemar Kornewald
586ca43389aSWaldemar Kornewald
587ca43389aSWaldemar Kornewaldvoid
588ca43389aSWaldemar KornewaldIPCP::TOBadEvent()
589ca43389aSWaldemar Kornewald{
590ca43389aSWaldemar Kornewald#if DEBUG
5916cfb4dcaSWaldemar Kornewald	dprintf("IPCP: TOBadEvent() state=%d\n", State());
592ca43389aSWaldemar Kornewald#endif
593ca43389aSWaldemar Kornewald
594ca43389aSWaldemar Kornewald	LockerHelper locker(fLock);
595ca43389aSWaldemar Kornewald
596ca43389aSWaldemar Kornewald	switch(State()) {
597ca43389aSWaldemar Kornewald		case PPP_CLOSING_STATE:
598ca43389aSWaldemar Kornewald			NewState(PPP_INITIAL_STATE);
599ca43389aSWaldemar Kornewald			locker.UnlockNow();
600ca43389aSWaldemar Kornewald			ReportDownEvent();
601ca43389aSWaldemar Kornewald		break;
602ca43389aSWaldemar Kornewald
603ca43389aSWaldemar Kornewald		case PPP_REQ_SENT_STATE:
604ca43389aSWaldemar Kornewald		case PPP_ACK_RCVD_STATE:
605ca43389aSWaldemar Kornewald		case PPP_ACK_SENT_STATE:
606ca43389aSWaldemar Kornewald			NewState(PPP_INITIAL_STATE);
607ca43389aSWaldemar Kornewald			locker.UnlockNow();
608ca43389aSWaldemar Kornewald			ReportUpFailedEvent();
609ca43389aSWaldemar Kornewald		break;
610ca43389aSWaldemar Kornewald
611ca43389aSWaldemar Kornewald		default:
612ca43389aSWaldemar Kornewald			IllegalEvent(PPP_TO_BAD_EVENT);
613ca43389aSWaldemar Kornewald	}
614ca43389aSWaldemar Kornewald}
615ca43389aSWaldemar Kornewald
616ca43389aSWaldemar Kornewald
617ca43389aSWaldemar Kornewaldvoid
618ca43389aSWaldemar KornewaldIPCP::RCREvent(struct mbuf *packet)
619ca43389aSWaldemar Kornewald{
620ca43389aSWaldemar Kornewald#if DEBUG
6216cfb4dcaSWaldemar Kornewald	dprintf("IPCP: RCREvent() state=%d\n", State());
622ca43389aSWaldemar Kornewald#endif
623ca43389aSWaldemar Kornewald
6241cea3d85SWaldemar Kornewald	KPPPConfigurePacket request(packet);
6251cea3d85SWaldemar Kornewald	KPPPConfigurePacket nak(PPP_CONFIGURE_NAK);
6261cea3d85SWaldemar Kornewald	KPPPConfigurePacket reject(PPP_CONFIGURE_REJECT);
627ca43389aSWaldemar Kornewald
628ca43389aSWaldemar Kornewald	// we should not use the same id as the peer
629ca43389aSWaldemar Kornewald	if(fID == mtod(packet, ppp_lcp_packet*)->id)
630ca43389aSWaldemar Kornewald		fID -= 128;
631ca43389aSWaldemar Kornewald
632ca43389aSWaldemar Kornewald	nak.SetID(request.ID());
633ca43389aSWaldemar Kornewald	reject.SetID(request.ID());
634ca43389aSWaldemar Kornewald
635ca43389aSWaldemar Kornewald	// parse each item
636ca43389aSWaldemar Kornewald	ppp_configure_item *item;
637ca43389aSWaldemar Kornewald	in_addr_t *requestedAddress, *wishedAddress = NULL;
638ca43389aSWaldemar Kornewald	for(int32 index = 0; index < request.CountItems(); index++) {
639ca43389aSWaldemar Kornewald		item = request.ItemAt(index);
640ca43389aSWaldemar Kornewald		if(!item)
641ca43389aSWaldemar Kornewald			continue;
642ca43389aSWaldemar Kornewald
643ca43389aSWaldemar Kornewald		// addresses have special handling to reduce code size
644ca43389aSWaldemar Kornewald		switch(item->type) {
645ca43389aSWaldemar Kornewald			case IPCP_ADDRESSES:
646ca43389aSWaldemar Kornewald				// abandoned by the standard
647ca43389aSWaldemar Kornewald			case IPCP_ADDRESS:
648ca43389aSWaldemar Kornewald				wishedAddress = &fPeerRequests.address;
649ca43389aSWaldemar Kornewald			break;
650ca43389aSWaldemar Kornewald
651ca43389aSWaldemar Kornewald			case IPCP_PRIMARY_DNS:
652ca43389aSWaldemar Kornewald				wishedAddress = &fPeerRequests.primaryDNS;
653ca43389aSWaldemar Kornewald			break;
654ca43389aSWaldemar Kornewald
655ca43389aSWaldemar Kornewald			case IPCP_SECONDARY_DNS:
656ca43389aSWaldemar Kornewald				wishedAddress = &fPeerRequests.secondaryDNS;
657ca43389aSWaldemar Kornewald			break;
658ca43389aSWaldemar Kornewald		}
659ca43389aSWaldemar Kornewald
660ca43389aSWaldemar Kornewald		// now parse item
661ca43389aSWaldemar Kornewald		switch(item->type) {
662ca43389aSWaldemar Kornewald			case IPCP_ADDRESSES:
663ca43389aSWaldemar Kornewald				// abandoned by the standard
664ca43389aSWaldemar Kornewald			case IPCP_ADDRESS:
665ca43389aSWaldemar Kornewald			case IPCP_PRIMARY_DNS:
666ca43389aSWaldemar Kornewald			case IPCP_SECONDARY_DNS:
667ca43389aSWaldemar Kornewald				if(item->length != 6) {
668ca43389aSWaldemar Kornewald					// the packet is invalid
669ca43389aSWaldemar Kornewald					m_freem(packet);
67093a59056SWaldemar Kornewald					NewState(PPP_INITIAL_STATE);
67193a59056SWaldemar Kornewald					ReportUpFailedEvent();
672ca43389aSWaldemar Kornewald					return;
673ca43389aSWaldemar Kornewald				}
674ca43389aSWaldemar Kornewald
675ca43389aSWaldemar Kornewald				requestedAddress = (in_addr_t*) item->data;
676ca43389aSWaldemar Kornewald				if(*wishedAddress == INADDR_ANY) {
677ca43389aSWaldemar Kornewald					if(*requestedAddress == INADDR_ANY) {
678ca43389aSWaldemar Kornewald						// we do not have an address for you
679ca43389aSWaldemar Kornewald						m_freem(packet);
68093a59056SWaldemar Kornewald						NewState(PPP_INITIAL_STATE);
68193a59056SWaldemar Kornewald						ReportUpFailedEvent();
682ca43389aSWaldemar Kornewald						return;
683ca43389aSWaldemar Kornewald					}
684ca43389aSWaldemar Kornewald				} else if(*requestedAddress != *wishedAddress) {
685ca43389aSWaldemar Kornewald					// we do not want this address
686ca43389aSWaldemar Kornewald					ip_item ipItem;
687ca43389aSWaldemar Kornewald					ipItem.type = item->type;
688ca43389aSWaldemar Kornewald					ipItem.length = 6;
689ca43389aSWaldemar Kornewald					ipItem.address = *wishedAddress;
690ca43389aSWaldemar Kornewald					nak.AddItem((ppp_configure_item*) &ipItem);
691ca43389aSWaldemar Kornewald				}
692ca43389aSWaldemar Kornewald			break;
693ca43389aSWaldemar Kornewald
694ca43389aSWaldemar Kornewald//			case IPCP_COMPRESSION_PROTOCOL:
695ca43389aSWaldemar Kornewald				// TODO: implement me!
696ca43389aSWaldemar Kornewald//			break;
697ca43389aSWaldemar Kornewald
698ca43389aSWaldemar Kornewald			default:
699ca43389aSWaldemar Kornewald				reject.AddItem(item);
700ca43389aSWaldemar Kornewald		}
701ca43389aSWaldemar Kornewald	}
702ca43389aSWaldemar Kornewald
703ca43389aSWaldemar Kornewald	// append additional values to the nak
704ca43389aSWaldemar Kornewald	if(!request.ItemWithType(IPCP_ADDRESS) && fPeerRequests.address == INADDR_ANY) {
705ca43389aSWaldemar Kornewald		// The peer did not provide us his address. Tell him to do so.
706ca43389aSWaldemar Kornewald		ip_item ipItem;
707ca43389aSWaldemar Kornewald		ipItem.type = IPCP_ADDRESS;
708ca43389aSWaldemar Kornewald		ipItem.length = 6;
709ca43389aSWaldemar Kornewald		ipItem.address = INADDR_ANY;
710ca43389aSWaldemar Kornewald		nak.AddItem((ppp_configure_item*) &ipItem);
711ca43389aSWaldemar Kornewald	}
712ca43389aSWaldemar Kornewald
713ca43389aSWaldemar Kornewald	if(nak.CountItems() > 0) {
714ca43389aSWaldemar Kornewald		RCRBadEvent(nak.ToMbuf(Interface().MRU(), Interface().PacketOverhead()), NULL);
715ca43389aSWaldemar Kornewald		m_freem(packet);
716ca43389aSWaldemar Kornewald	} else if(reject.CountItems() > 0) {
717ca43389aSWaldemar Kornewald		RCRBadEvent(NULL, reject.ToMbuf(Interface().MRU(),
718ca43389aSWaldemar Kornewald			Interface().PacketOverhead()));
719ca43389aSWaldemar Kornewald		m_freem(packet);
720ca43389aSWaldemar Kornewald	} else
721ca43389aSWaldemar Kornewald		RCRGoodEvent(packet);
722ca43389aSWaldemar Kornewald}
723ca43389aSWaldemar Kornewald
724ca43389aSWaldemar Kornewald
725ca43389aSWaldemar Kornewaldvoid
726ca43389aSWaldemar KornewaldIPCP::RCRGoodEvent(struct mbuf *packet)
727ca43389aSWaldemar Kornewald{
728ca43389aSWaldemar Kornewald#if DEBUG
7296cfb4dcaSWaldemar Kornewald	dprintf("IPCP: RCRGoodEvent() state=%d\n", State());
730ca43389aSWaldemar Kornewald#endif
731ca43389aSWaldemar Kornewald
732ca43389aSWaldemar Kornewald	LockerHelper locker(fLock);
733ca43389aSWaldemar Kornewald
734ca43389aSWaldemar Kornewald	switch(State()) {
735ca43389aSWaldemar Kornewald		case PPP_INITIAL_STATE:
736ca43389aSWaldemar Kornewald			NewState(PPP_ACK_SENT_STATE);
737ca43389aSWaldemar Kornewald			InitializeRestartCount();
738ca43389aSWaldemar Kornewald			locker.UnlockNow();
739ca43389aSWaldemar Kornewald			SendConfigureRequest();
740ca43389aSWaldemar Kornewald			SendConfigureAck(packet);
741ca43389aSWaldemar Kornewald		break;
742ca43389aSWaldemar Kornewald
743ca43389aSWaldemar Kornewald		case PPP_REQ_SENT_STATE:
744ca43389aSWaldemar Kornewald			NewState(PPP_ACK_SENT_STATE);
745ca43389aSWaldemar Kornewald
746ca43389aSWaldemar Kornewald		case PPP_ACK_SENT_STATE:
747ca43389aSWaldemar Kornewald			locker.UnlockNow();
748ca43389aSWaldemar Kornewald			SendConfigureAck(packet);
749ca43389aSWaldemar Kornewald		break;
750ca43389aSWaldemar Kornewald
751ca43389aSWaldemar Kornewald		case PPP_ACK_RCVD_STATE:
752ca43389aSWaldemar Kornewald			NewState(PPP_OPENED_STATE);
753ca43389aSWaldemar Kornewald			locker.UnlockNow();
754ca43389aSWaldemar Kornewald			SendConfigureAck(packet);
755ca43389aSWaldemar Kornewald			ReportUpEvent();
756ca43389aSWaldemar Kornewald		break;
757ca43389aSWaldemar Kornewald
758ca43389aSWaldemar Kornewald		case PPP_OPENED_STATE:
759ca43389aSWaldemar Kornewald			NewState(PPP_ACK_SENT_STATE);
760ca43389aSWaldemar Kornewald			locker.UnlockNow();
761ca43389aSWaldemar Kornewald			SendConfigureRequest();
762ca43389aSWaldemar Kornewald			SendConfigureAck(packet);
763ca43389aSWaldemar Kornewald		break;
764ca43389aSWaldemar Kornewald
765ca43389aSWaldemar Kornewald		default:
766ca43389aSWaldemar Kornewald			m_freem(packet);
767ca43389aSWaldemar Kornewald	}
768ca43389aSWaldemar Kornewald}
769ca43389aSWaldemar Kornewald
770ca43389aSWaldemar Kornewald
771ca43389aSWaldemar Kornewaldvoid
772ca43389aSWaldemar KornewaldIPCP::RCRBadEvent(struct mbuf *nak, struct mbuf *reject)
773ca43389aSWaldemar Kornewald{
774ca43389aSWaldemar Kornewald#if DEBUG
7756cfb4dcaSWaldemar Kornewald	dprintf("IPCP: RCRBadEvent() state=%d\n", State());
776ca43389aSWaldemar Kornewald#endif
777ca43389aSWaldemar Kornewald
778ca43389aSWaldemar Kornewald	LockerHelper locker(fLock);
779ca43389aSWaldemar Kornewald
780ca43389aSWaldemar Kornewald	switch(State()) {
781ca43389aSWaldemar Kornewald		case PPP_OPENED_STATE:
782ca43389aSWaldemar Kornewald			NewState(PPP_REQ_SENT_STATE);
783ca43389aSWaldemar Kornewald			locker.UnlockNow();
784ca43389aSWaldemar Kornewald			SendConfigureRequest();
785ca43389aSWaldemar Kornewald
786ca43389aSWaldemar Kornewald		case PPP_ACK_SENT_STATE:
787ca43389aSWaldemar Kornewald			if(State() == PPP_ACK_SENT_STATE)
788ca43389aSWaldemar Kornewald				NewState(PPP_REQ_SENT_STATE);
789ca43389aSWaldemar Kornewald					// OPENED_STATE might have set this already
790ca43389aSWaldemar Kornewald
791ca43389aSWaldemar Kornewald		case PPP_INITIAL_STATE:
792ca43389aSWaldemar Kornewald		case PPP_REQ_SENT_STATE:
793ca43389aSWaldemar Kornewald		case PPP_ACK_RCVD_STATE:
794ca43389aSWaldemar Kornewald			locker.UnlockNow();
795ca43389aSWaldemar Kornewald			if(nak && ntohs(mtod(nak, ppp_lcp_packet*)->length) > 3)
796ca43389aSWaldemar Kornewald				SendConfigureNak(nak);
797ca43389aSWaldemar Kornewald			else if(reject && ntohs(mtod(reject, ppp_lcp_packet*)->length) > 3)
798ca43389aSWaldemar Kornewald				SendConfigureNak(reject);
799ca43389aSWaldemar Kornewald		return;
800ca43389aSWaldemar Kornewald			// prevents the nak/reject from being m_freem()'d
801ca43389aSWaldemar Kornewald
802ca43389aSWaldemar Kornewald		default:
803ca43389aSWaldemar Kornewald			;
804ca43389aSWaldemar Kornewald	}
805ca43389aSWaldemar Kornewald
806ca43389aSWaldemar Kornewald	if(nak)
807ca43389aSWaldemar Kornewald		m_freem(nak);
808ca43389aSWaldemar Kornewald	if(reject)
809ca43389aSWaldemar Kornewald		m_freem(reject);
810