1/*
2 * Copyright 2003-2006, Waldemar Kornewald <wkornew@gmx.net>
3 * Distributed under the terms of the MIT License.
4 */
5
6#if DEBUG
7#include <cstdio>
8#endif
9
10#include "Protocol.h"
11#include "IPCP.h"
12#include <KPPPConfigurePacket.h>
13#include <KPPPInterface.h>
14#include <settings_tools.h>
15
16#include <PPPoEDevice.h>
17
18#include <cstring>
19
20#include <arpa/inet.h>
21#include <net_buffer.h>
22#include <net_stack.h>
23#include <net/route.h>
24#include <sys/sockio.h>
25
26// For updating resolv.conf
27#include <ctype.h>
28#include <fcntl.h>
29#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
32#include <unistd.h>
33
34#define RESOLV_CONF_FILE "/boot/system/settings/network/resolv.conf"
35
36extern net_buffer_module_info *gBufferModule;
37static struct net_datalink_module_info *sDatalinkModule;
38static struct net_stack_module_info *sStackModule;
39
40#if DEBUG
41#include <unistd.h>
42
43static int sFD;
44	// the file descriptor for debug output
45static char sDigits[] = "0123456789ABCDEF";
46void
47dump_packet(net_buffer *packet, const char *direction)
48{
49	if (!packet)
50		return;
51
52	uint8 *data = mtod(packet, uint8*);
53	uint8 buffer[128];
54	uint8 bufferIndex = 0;
55
56	sprintf((char*) buffer, "Dumping %s packet;len=%ld;pkthdr.len=%d\n", direction,
57		packet->m_len, packet->m_flags & M_PKTHDR ? packet->m_pkthdr.len : -1);
58	write(sFD, buffer, strlen((char*) buffer));
59
60	for (uint32 index = 0; index < packet->m_len; index++) {
61		buffer[bufferIndex++] = sDigits[data[index] >> 4];
62		buffer[bufferIndex++] = sDigits[data[index] & 0x0F];
63		if (bufferIndex == 32 || index == packet->m_len - 1) {
64			buffer[bufferIndex++] = '\n';
65			buffer[bufferIndex] = 0;
66			write(sFD, buffer, strlen((char*) buffer));
67			bufferIndex = 0;
68		}
69	}
70}
71#endif
72
73
74static const bigtime_t kIPCPStateMachineTimeout = 3000000;
75	// 3 seconds
76
77
78IPCP::IPCP(KPPPInterface& interface, driver_parameter *settings)
79	: KPPPProtocol("IPCP", PPP_NCP_PHASE, IPCP_PROTOCOL, PPP_PROTOCOL_LEVEL,
80		AF_INET, 0, interface, settings, PPP_INCLUDES_NCP),
81	fDefaultRoute(NULL),
82	fRequestPrimaryDNS(false),
83	fRequestSecondaryDNS(false),
84	fState(PPP_INITIAL_STATE),
85	fID(system_time() & 0xFF),
86	fMaxRequest(10),
87	fMaxTerminate(2),
88	fMaxNak(5),
89	fRequestID(0),
90	fTerminateID(0),
91	fNextTimeout(0)
92{
93	// reset configurations
94	memset(&fLocalConfiguration, 0, sizeof(ipcp_configuration));
95	memset(&fPeerConfiguration, 0, sizeof(ipcp_configuration));
96
97	// reset requests
98	memset(&fLocalRequests, 0, sizeof(ipcp_requests));
99	memset(&fPeerRequests, 0, sizeof(ipcp_requests));
100
101	// Parse settings:
102	// "Local" and "Peer" describe each side's settings
103	ParseSideRequests(get_parameter_with_name(IPCP_LOCAL_SIDE_KEY, Settings()),
104		PPP_LOCAL_SIDE);
105	ParseSideRequests(get_parameter_with_name(IPCP_PEER_SIDE_KEY, Settings()),
106		PPP_PEER_SIDE);
107
108	get_module(NET_STACK_MODULE_NAME, (module_info **)&sStackModule);
109	get_module(NET_DATALINK_MODULE_NAME, (module_info **)&sDatalinkModule);
110#if DEBUG
111	sFD = open("/boot/home/ipcpdebug", O_WRONLY | O_CREAT | O_TRUNC);
112#endif
113}
114
115
116IPCP::~IPCP()
117{
118
119	put_module(NET_DATALINK_MODULE_NAME);
120	put_module(NET_STACK_MODULE_NAME);
121#if DEBUG
122	close(sFD);
123#endif
124}
125
126
127void
128IPCP::Uninit()
129{
130	RemoveRoutes();
131}
132
133
134status_t
135IPCP::StackControl(uint32 op, void *data)
136{
137	TRACE("IPCP: StackControl(op=%ld)\n", op);
138
139	// TODO:
140	// check values
141
142	switch (op) {
143		case SIOCSIFADDR:
144		break;
145
146		case SIOCSIFFLAGS:
147		break;
148
149		case SIOCSIFDSTADDR:
150		break;
151
152		case SIOCSIFNETMASK:
153		break;
154
155		default:
156			ERROR("IPCP: Unknown ioctl: %" B_PRIu32 "\n", op);
157			return KPPPProtocol::StackControl(op, data);
158	}
159
160	return B_OK;
161}
162
163
164bool
165IPCP::Up()
166{
167	TRACE("IPCP: Up() state=%d\n", State());
168
169	// Servers do not send a configure-request when Up() is called. They wait until
170	// the client requests this protocol.
171	if (Interface().Mode() == PPP_SERVER_MODE)
172		return true;
173
174	switch (State()) {
175		case PPP_INITIAL_STATE:
176			NewState(PPP_REQ_SENT_STATE);
177			InitializeRestartCount();
178			SendConfigureRequest();
179		break;
180
181		default:
182			;
183	}
184
185	return true;
186}
187
188
189bool
190IPCP::Down()
191{
192	TRACE("IPCP: Down() state=%d\n", State());
193
194	switch (Interface().Phase()) {
195		case PPP_DOWN_PHASE:
196			// interface finished terminating
197			NewState(PPP_INITIAL_STATE);
198			ReportDownEvent();
199				// this will also reset and update addresses
200		break;
201
202/*		case PPP_TERMINATION_PHASE:
203			// interface is terminating
204		break;
205
206		case PPP_ESTABLISHMENT_PHASE:
207			// interface is reconfiguring
208		break;
209*/
210		case PPP_ESTABLISHED_PHASE:
211			// terminate this NCP individually (block until we finished terminating)
212			if (State() != PPP_INITIAL_STATE && State() != PPP_CLOSING_STATE) {
213				NewState(PPP_CLOSING_STATE);
214				InitializeRestartCount();
215				SendTerminateRequest();
216			}
217
218			while (State() == PPP_CLOSING_STATE)
219				snooze(50000);
220		break;
221
222		default:
223			;
224	}
225
226	return true;
227}
228
229
230status_t
231IPCP::Send(net_buffer *packet, uint16 protocolNumber)
232{
233	TRACE("IPCP: Send(0x%X)\n", protocolNumber);
234
235	if ((protocolNumber == IP_PROTOCOL && State() == PPP_OPENED_STATE)
236			|| protocolNumber == IPCP_PROTOCOL) {
237#if DEBUG
238		dump_packet(packet, "outgoing");
239#endif
240		Interface().UpdateIdleSince();
241		return SendToNext(packet, protocolNumber);
242	}
243
244	ERROR("IPCP: Send() failed because of wrong state or protocol number!\n");
245
246	gBufferModule->free(packet);
247	return B_ERROR;
248}
249
250
251status_t
252IPCP::Receive(net_buffer *packet, uint16 protocolNumber)
253{
254	TRACE("IPCP: Receive(0x%X)\n", protocolNumber);
255
256	if (!packet)
257		return B_ERROR;
258
259	if (protocolNumber == IP_PROTOCOL)
260		return ReceiveIPPacket(packet, protocolNumber);
261
262	if (protocolNumber != IPCP_PROTOCOL)
263		return PPP_UNHANDLED;
264
265	NetBufferHeaderReader<ppp_lcp_packet> bufferheader(packet);
266	if (bufferheader.Status() != B_OK)
267		return B_ERROR;
268	ppp_lcp_packet &data = bufferheader.Data();
269
270	if (ntohs(data.length) < 4)
271		return B_ERROR;
272
273	// packet is freed by event methods
274	switch (data.code) {
275		case PPP_CONFIGURE_REQUEST:
276			RCREvent(packet);
277		break;
278
279		case PPP_CONFIGURE_ACK:
280			RCAEvent(packet);
281		break;
282
283		case PPP_CONFIGURE_NAK:
284		case PPP_CONFIGURE_REJECT:
285			RCNEvent(packet);
286		break;
287
288		case PPP_TERMINATE_REQUEST:
289			RTREvent(packet);
290		break;
291
292		case PPP_TERMINATE_ACK:
293			RTAEvent(packet);
294		break;
295
296		case PPP_CODE_REJECT:
297			RXJBadEvent(packet);
298				// we implemented the minimum requirements
299		break;
300
301		default:
302			RUCEvent(packet);
303			return PPP_REJECTED;
304	}
305
306	return B_OK;
307}
308
309
310status_t
311IPCP::ReceiveIPPacket(net_buffer *packet, uint16 protocolNumber)
312{
313	if (protocolNumber != IP_PROTOCOL || State() != PPP_OPENED_STATE)
314		return PPP_UNHANDLED;
315
316	// TODO: add VJC support (the packet would be decoded here)
317
318	if (packet) {
319#if DEBUG
320		dump_packet(packet, "incoming");
321#endif
322		Interface().UpdateIdleSince();
323
324		TRACE("We got 1 IP packet from %s::%s\n", __FILE__, __func__);
325		gBufferModule->free(packet);
326		return B_OK;
327	} else {
328		ERROR("IPCP: Error: Could not find input function for IP!\n");
329		gBufferModule->free(packet);
330		return B_ERROR;
331	}
332}
333
334
335void
336IPCP::Pulse()
337{
338	if (fNextTimeout == 0 || fNextTimeout > system_time())
339		return;
340	fNextTimeout = 0;
341
342	switch (State()) {
343		case PPP_CLOSING_STATE:
344			if (fTerminateCounter <= 0)
345				TOBadEvent();
346			else
347				TOGoodEvent();
348		break;
349
350		case PPP_REQ_SENT_STATE:
351		case PPP_ACK_RCVD_STATE:
352		case PPP_ACK_SENT_STATE:
353			if (fRequestCounter <= 0)
354				TOBadEvent();
355			else
356				TOGoodEvent();
357		break;
358
359		default:
360			;
361	}
362}
363
364
365bool
366IPCP::ParseSideRequests(const driver_parameter *requests, ppp_side side)
367{
368	if (!requests)
369		return false;
370
371	ipcp_requests *selectedRequests;
372
373	if (side == PPP_LOCAL_SIDE) {
374		selectedRequests = &fLocalRequests;
375		fRequestPrimaryDNS = fRequestSecondaryDNS = false;
376	} else
377		selectedRequests = &fPeerRequests;
378
379	memset(selectedRequests, 0, sizeof(ipcp_requests));
380		// reset current requests
381
382	// The following values are allowed:
383	//  "Address"		the ip address that will be suggested
384	//  "Netmask"		the netmask that should be used
385	//  "PrimaryDNS"	primary DNS server
386	//  "SecondaryDNS"	secondary DNS server
387	// Setting any value to 0.0.0.0 or "auto" means it should be chosen automatically.
388
389	in_addr_t address = INADDR_ANY;
390	for (int32 index = 0; index < requests->parameter_count; index++) {
391		if (requests->parameters[index].value_count == 0)
392			continue;
393
394		// all values are IP addresses, so parse the address here
395		if (strcasecmp(requests->parameters[index].values[0], "auto")) {
396			address = inet_addr(requests->parameters[index].values[0]);
397			// address = INADDR_ANY;
398			if (address == INADDR_NONE)
399				continue;
400		}
401
402		if (!strcasecmp(requests->parameters[index].name, IPCP_IP_ADDRESS_KEY))
403			selectedRequests->address = address;
404		else if (!strcasecmp(requests->parameters[index].name, IPCP_NETMASK_KEY))
405			selectedRequests->netmask = address;
406		else if (!strcasecmp(requests->parameters[index].name, IPCP_PRIMARY_DNS_KEY)) {
407			selectedRequests->primaryDNS = address;
408			if (side == PPP_LOCAL_SIDE)
409				fRequestPrimaryDNS = true;
410		} else if (!strcasecmp(requests->parameters[index].name,
411				IPCP_SECONDARY_DNS_KEY)) {
412			selectedRequests->secondaryDNS = address;
413			if (side == PPP_LOCAL_SIDE)
414				fRequestSecondaryDNS = true;
415		}
416	}
417
418	return true;
419}
420
421
422net_interface *
423get_interface_by_name(net_domain *domain, const char *name)
424{
425	ifreq request;
426	memset(&request, 0, sizeof(request));
427	size_t size = sizeof(request);
428
429	strlcpy(request.ifr_name, name, IF_NAMESIZE);
430
431	if (sDatalinkModule->control(domain, SIOCGIFINDEX, &request, &size) != B_OK) {
432		TRACE("sDatalinkModule->control failure\n");
433		return NULL;
434	}
435	return sDatalinkModule->get_interface(domain, request.ifr_index);
436}
437
438
439status_t
440set_interface_address(net_domain* domain, struct ifaliasreq* inreq)
441{
442	size_t size = sizeof(struct ifaliasreq);
443	return sDatalinkModule->control(domain, B_SOCKET_SET_ALIAS, inreq, &size);
444}
445
446
447void
448IPCP::UpdateAddresses()
449{
450	TRACE("%s::%s: entering UpdateAddresses\n", __FILE__, __func__);
451	RemoveRoutes();
452
453	if (State() != PPP_OPENED_STATE && !Interface().DoesConnectOnDemand())
454		return;
455
456	TRACE("%s::%s: entering ChangeAddress\n", __FILE__, __func__);
457	if (sDatalinkModule == NULL) {
458		TRACE("%s::%s: some module not found!\n", __FILE__, __func__);
459		return;
460	}
461
462
463	struct sockaddr newAddr = {6, AF_INET, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
464	struct sockaddr netmask = {6, AF_INET, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
465	struct sockaddr broadaddr = {6, AF_INET, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
466
467	if (fLocalRequests.address != INADDR_ANY)
468		memcpy(newAddr.sa_data + 2, &fLocalRequests.address, sizeof(in_addr_t));
469	else if (fLocalConfiguration.address == INADDR_ANY) {
470		in_addr_t inaddrBroadcast = 0x010F0F0F; // was: INADDR_BROADCAST
471		memcpy(newAddr.sa_data + 2, &inaddrBroadcast, sizeof(in_addr_t));
472	} else
473		memcpy(newAddr.sa_data + 2, &fLocalConfiguration.address, sizeof(in_addr_t));
474
475	struct ifaliasreq inreq;
476	memset(&inreq, 0, sizeof(struct ifaliasreq));
477	memcpy(inreq.ifra_name, Interface().Name(), IF_NAMESIZE);
478	memcpy(&inreq.ifra_addr, &newAddr, sizeof(struct sockaddr));
479	memcpy(&inreq.ifra_mask, &netmask, sizeof(struct sockaddr));
480	memcpy(&inreq.ifra_broadaddr, &broadaddr, sizeof(struct sockaddr));
481	inreq.ifra_index = -1;
482		// create a new interface address
483		// Is it OK when we already have one?
484		// test case:	ifconfig ppp up
485		// 		ifconfig ppp down
486		// 		ifconfig ppp up
487		// 		check if some weird things happen
488
489	net_domain* domain = sStackModule->get_domain(AF_INET);
490	status_t status = set_interface_address(domain, &inreq);
491
492	if (status != B_OK) {
493		TRACE("%s:%s: set_interface_address Fail!!!!\n", __FILE__, __func__);
494		return;
495	}
496	TRACE("%s:%s: set_interface_address fine\n", __FILE__, __func__);
497
498
499	net_interface* pppInterface = get_interface_by_name(domain, Interface().Name());
500	if (pppInterface == NULL) {
501		TRACE("%s::%s: pppInterface not found!\n", __FILE__, __func__);
502		return;
503	}
504
505	net_interface_address* pppInterfaceAddress = NULL;
506	while (sDatalinkModule->get_next_interface_address(pppInterface,
507				&pppInterfaceAddress)) {
508		if (pppInterfaceAddress->domain->family != AF_INET)
509			continue;
510		break;
511	}
512
513	// add default/subnet route
514	if (Side() == PPP_LOCAL_SIDE && pppInterfaceAddress != NULL) {
515		struct sockaddr addrGateway = {8, AF_INET, {0x00, 0x00, 0x00, 0x00,
516			0x00, 0x00} };
517
518		// create destination address
519		if (fPeerRequests.address != INADDR_ANY)
520			memcpy(addrGateway.sa_data + 2, &fPeerRequests.address,
521				sizeof(in_addr_t));
522		else if (fPeerConfiguration.address == INADDR_ANY) {
523			in_addr_t gateway = 0x020F0F0F;
524			memcpy(addrGateway.sa_data + 2, &gateway, sizeof(in_addr_t));
525				// was: INADDR_BROADCAST
526		} else
527			memcpy(addrGateway.sa_data + 2, &fPeerConfiguration.address,
528				sizeof(in_addr_t));
529
530		net_route defaultRoute;
531		defaultRoute.destination = NULL;
532		defaultRoute.mask = NULL;
533		defaultRoute.gateway = &addrGateway;
534		defaultRoute.flags = RTF_DEFAULT | RTF_GATEWAY;
535		defaultRoute.interface_address = pppInterfaceAddress;
536			// route->interface_address;
537
538		status_t status = sDatalinkModule->add_route(domain, &defaultRoute);
539		if (status == B_OK)
540			dprintf("%s::%s: add route default OK!\n", __FILE__, __func__);
541		else
542			dprintf("%s::%s: add route default Fail!\n", __FILE__, __func__);
543
544		sDatalinkModule->put_interface_address(pppInterfaceAddress);
545	}
546
547	if (Side() == PPP_LOCAL_SIDE) {
548		int file;
549		int primary_dns, secondary_dns;
550		char buf[256];
551
552		file = open(RESOLV_CONF_FILE, O_RDWR);
553
554		primary_dns = ntohl(fLocalConfiguration.primaryDNS);
555		secondary_dns = ntohl(fLocalConfiguration.secondaryDNS);
556
557		sprintf(buf, "%s\t%d.%d.%d.%d\n%s\t%d.%d.%d.%d\n",
558				"nameserver",
559				(primary_dns & 0xff000000) >> 24,
560				(primary_dns & 0x00ff0000) >> 16,
561				(primary_dns & 0x0000ff00) >> 8,
562				(primary_dns & 0x000000ff),
563				"nameserver",
564				(secondary_dns & 0xff000000) >> 24,
565				(secondary_dns & 0x00ff0000) >> 16,
566				(secondary_dns & 0x0000ff00) >> 8,
567				(secondary_dns & 0x000000ff));
568
569		write(file, buf, strlen(buf));
570		close(file);
571	}
572}
573
574
575void
576IPCP::RemoveRoutes()
577{
578	// note:
579	// 	haiku supports multi default route. But for Desktop, ppp is generally
580	// 	the only default route. So is it necessary to remove other default
581	// 	route?
582	TRACE("%s::%s: entering RemoveRoutes!\n", __FILE__, __func__);
583
584	char *ethernetName = NULL;
585	PPPoEDevice* pppoeDevice = (PPPoEDevice *)Interface().Device();
586	if (pppoeDevice == NULL)
587		return;
588	ethernetName = pppoeDevice->EthernetIfnet()->name;
589	if (ethernetName == NULL)
590		return;
591
592	net_domain* domain = sStackModule->get_domain(AF_INET);
593	net_interface* pppInterface = get_interface_by_name(domain, ethernetName);
594
595	if (pppInterface == NULL) {
596		TRACE("%s::%s: pppInterface not found!\n", __FILE__, __func__);
597		return;
598	}
599
600	net_interface_address* pppInterfaceAddress = NULL;
601
602	while (sDatalinkModule->get_next_interface_address(pppInterface,
603				&pppInterfaceAddress)) {
604		if (pppInterfaceAddress->domain->family != AF_INET)
605			continue;
606
607		net_route oldDefaultRoute;
608		oldDefaultRoute.destination = NULL;
609		oldDefaultRoute.mask = NULL;
610		oldDefaultRoute.gateway = NULL;
611		oldDefaultRoute.flags= RTF_DEFAULT;
612		oldDefaultRoute.interface_address = pppInterfaceAddress;
613
614		status_t status = sDatalinkModule->remove_route(domain, &oldDefaultRoute);
615			// current: can not get the system default route so we fake
616			// 	    one default route for delete
617			// Todo: save the oldDefaultRoute to fDefaultRoute
618			// 	 restore the fDefaultRoute when ppp is down
619
620		sDatalinkModule->put_interface_address(pppInterfaceAddress);
621
622		if (status == B_OK)
623			dprintf("IPCP::RemoveRoutes: remove old default route OK!\n");
624		else
625			dprintf("IPCP::RemoveRoutes: remove old default route Fail!\n");
626
627		break;
628	}
629
630	if (fDefaultRoute) {
631		struct sockaddr_in netmask;
632		memset(&netmask, 0, sizeof(struct sockaddr_in));
633
634		netmask.sin_family = AF_INET;
635		netmask.sin_addr.s_addr = fLocalRequests.netmask;
636		netmask.sin_len = sizeof(struct sockaddr_in);
637
638		// if (rtrequest(RTM_DELETE, (struct sockaddr*) &netmask,
639				// (struct sockaddr*) &fGateway, (struct sockaddr*) &netmask,
640				// RTF_UP | RTF_GATEWAY, &fDefaultRoute) != B_OK)
641			ERROR("IPCP: RemoveRoutes(): could not remove default/subnet route!\n");
642
643		fDefaultRoute = NULL;
644	}
645}
646
647
648uint8
649IPCP::NextID()
650{
651	return (uint8) atomic_add(&fID, 1);
652}
653
654
655void
656IPCP::NewState(ppp_state next)
657{
658	TRACE("IPCP: NewState(%d) state=%d\n", next, State());
659
660	// report state changes
661	if (State() == PPP_INITIAL_STATE && next != State())
662		UpStarted();
663	else if (State() == PPP_OPENED_STATE && next != State())
664		DownStarted();
665
666	// maybe we do not need the timer anymore
667	if (next < PPP_CLOSING_STATE || next == PPP_OPENED_STATE)
668		fNextTimeout = 0;
669
670	fState = next;
671}
672
673
674void
675IPCP::TOGoodEvent()
676{
677#if DEBUG
678	printf("IPCP: TOGoodEvent() state=%d\n", State());
679#endif
680
681	switch (State()) {
682		case PPP_CLOSING_STATE:
683			SendTerminateRequest();
684		break;
685
686		case PPP_ACK_RCVD_STATE:
687			NewState(PPP_REQ_SENT_STATE);
688
689		case PPP_REQ_SENT_STATE:
690		case PPP_ACK_SENT_STATE:
691			SendConfigureRequest();
692		break;
693
694		default:
695			IllegalEvent(PPP_TO_GOOD_EVENT);
696	}
697}
698
699
700void
701IPCP::TOBadEvent()
702{
703	TRACE("IPCP: TOBadEvent() state=%d\n", State());
704
705	switch (State()) {
706		case PPP_CLOSING_STATE:
707			NewState(PPP_INITIAL_STATE);
708			ReportDownEvent();
709		break;
710
711		case PPP_REQ_SENT_STATE:
712		case PPP_ACK_RCVD_STATE:
713		case PPP_ACK_SENT_STATE:
714			NewState(PPP_INITIAL_STATE);
715			ReportUpFailedEvent();
716		break;
717
718		default:
719			IllegalEvent(PPP_TO_BAD_EVENT);
720	}
721}
722
723
724void
725IPCP::RCREvent(net_buffer *packet)
726{
727	TRACE("IPCP: RCREvent() state=%d\n", State());
728
729	KPPPConfigurePacket request(packet);
730	KPPPConfigurePacket nak(PPP_CONFIGURE_NAK);
731	KPPPConfigurePacket reject(PPP_CONFIGURE_REJECT);
732
733	NetBufferHeaderReader<ppp_lcp_packet> bufferheader(packet);
734	if (bufferheader.Status() != B_OK)
735		return;
736	ppp_lcp_packet &lcpHeader = bufferheader.Data();
737
738	// we should not use the same id as the peer
739	if (fID == lcpHeader.id)
740		fID -= 128;
741
742	nak.SetID(request.ID());
743	reject.SetID(request.ID());
744
745	// parse each item
746	ppp_configure_item *item;
747	in_addr_t *requestedAddress, *wishedAddress = NULL;
748	for (int32 index = 0; index < request.CountItems(); index++) {
749		item = request.ItemAt(index);
750		if (!item)
751			continue;
752
753		// addresses have special handling to reduce code size
754		switch (item->type) {
755			case IPCP_ADDRESSES:
756				// abandoned by the standard
757			case IPCP_ADDRESS:
758				wishedAddress = &fPeerRequests.address;
759			break;
760
761			case IPCP_PRIMARY_DNS:
762				wishedAddress = &fPeerRequests.primaryDNS;
763			break;
764
765			case IPCP_SECONDARY_DNS:
766				wishedAddress = &fPeerRequests.secondaryDNS;
767			break;
768		}
769
770		// now parse item
771		switch (item->type) {
772			case IPCP_ADDRESSES:
773				// abandoned by the standard
774			case IPCP_ADDRESS:
775			case IPCP_PRIMARY_DNS:
776			case IPCP_SECONDARY_DNS:
777				if (item->length != 6) {
778					// the packet is invalid
779					gBufferModule->free(packet);
780					NewState(PPP_INITIAL_STATE);
781					ReportUpFailedEvent();
782					return;
783				}
784
785				requestedAddress = (in_addr_t*) item->data;
786				if (*wishedAddress == INADDR_ANY) {
787					if (*requestedAddress == INADDR_ANY) {
788						// we do not have an address for you
789						gBufferModule->free(packet);
790						NewState(PPP_INITIAL_STATE);
791						ReportUpFailedEvent();
792						return;
793					}
794				} else if (*requestedAddress != *wishedAddress) {
795					// we do not want this address
796					ip_item ipItem;
797					ipItem.type = item->type;
798					ipItem.length = 6;
799					ipItem.address = *wishedAddress;
800					nak.AddItem((ppp_configure_item*) &ipItem);
801				}
802			break;
803
804//			case IPCP_COMPRESSION_PROTOCOL:
805				// TODO: implement me!
806//			break;
807
808			default:
809				reject.AddItem(item);
810		}
811	}
812
813	// append additional values to the nak
814	if (!request.ItemWithType(IPCP_ADDRESS) && fPeerRequests.address == INADDR_ANY) {
815		// The peer did not provide us his address. Tell him to do so.
816		ip_item ipItem;
817		ipItem.type = IPCP_ADDRESS;
818		ipItem.length = 6;
819		ipItem.address = INADDR_ANY;
820		nak.AddItem((ppp_configure_item*) &ipItem);
821	}
822
823	if (nak.CountItems() > 0) {
824		RCRBadEvent(nak.ToNetBuffer(Interface().MRU()), NULL);
825		gBufferModule->free(packet);
826	} else if (reject.CountItems() > 0) {
827		RCRBadEvent(NULL, reject.ToNetBuffer(Interface().MRU()));
828		gBufferModule->free(packet);
829	} else
830		RCRGoodEvent(packet);
831}
832
833
834void
835IPCP::RCRGoodEvent(net_buffer *packet)
836{
837	TRACE("IPCP: RCRGoodEvent() state=%d\n", State());
838
839	switch (State()) {
840		case PPP_INITIAL_STATE:
841			NewState(PPP_ACK_SENT_STATE);
842			InitializeRestartCount();
843			SendConfigureRequest();
844			SendConfigureAck(packet);
845		break;
846
847		case PPP_REQ_SENT_STATE:
848			NewState(PPP_ACK_SENT_STATE);
849
850		case PPP_ACK_SENT_STATE:
851			SendConfigureAck(packet);
852		break;
853
854		case PPP_ACK_RCVD_STATE:
855			NewState(PPP_OPENED_STATE);
856			SendConfigureAck(packet);
857			ReportUpEvent();
858		break;
859
860		case PPP_OPENED_STATE:
861			NewState(PPP_ACK_SENT_STATE);
862			SendConfigureRequest();
863			SendConfigureAck(packet);
864		break;
865
866		default:
867			gBufferModule->free(packet);
868	}
869}
870
871
872void
873IPCP::RCRBadEvent(net_buffer *nak, net_buffer *reject)
874{
875	TRACE("IPCP: RCRBadEvent() state=%d\n", State());
876
877	uint16 lcpHdrRejectLength = 0;
878	uint16 lcpHdrNakLength = 0;
879
880	if (nak) {
881		NetBufferHeaderReader<ppp_lcp_packet> nakBufferHeaderReader(nak);
882		if (nakBufferHeaderReader.Status() != B_OK)
883			return;
884		ppp_lcp_packet &lcpNakPacket = nakBufferHeaderReader.Data();
885		lcpHdrNakLength = lcpNakPacket.length;
886	}
887
888
889	if (reject) {
890		NetBufferHeaderReader<ppp_lcp_packet> rejectBufferHeaderReader(reject);
891		if (rejectBufferHeaderReader.Status() != B_OK)
892			return;
893		ppp_lcp_packet &lcpRejectPacket = rejectBufferHeaderReader.Data();
894		lcpHdrRejectLength = lcpRejectPacket.length;
895	}
896
897	switch (State()) {
898		case PPP_OPENED_STATE:
899			NewState(PPP_REQ_SENT_STATE);
900			SendConfigureRequest();
901
902		case PPP_ACK_SENT_STATE:
903			if (State() == PPP_ACK_SENT_STATE)
904				NewState(PPP_REQ_SENT_STATE);
905					// OPENED_STATE might have set this already
906
907		case PPP_INITIAL_STATE:
908		case PPP_REQ_SENT_STATE:
909		case PPP_ACK_RCVD_STATE:
910			if (nak && ntohs(lcpHdrNakLength) > 3)
911				SendConfigureNak(nak);
912			else if (reject && ntohs(lcpHdrRejectLength) > 3)
913				SendConfigureNak(reject);
914		return;
915			// prevents the nak/reject from being m_freem()'d
916
917		default:
918			;
919	}
920
921	if (nak)
922		gBufferModule->free(nak);
923	if (reject)
924		gBufferModule->free(reject);
925}
926
927
928void
929IPCP::RCAEvent(net_buffer *packet)
930{
931	ERROR("IPCP: RCAEvent() state=%d\n", State());
932
933	NetBufferHeaderReader<ppp_lcp_packet> bufferheader(packet);
934	if (bufferheader.Status() != B_OK)
935		return;
936	ppp_lcp_packet &lcpHeader = bufferheader.Data();
937	if (fRequestID != lcpHeader.id) {
938		// this packet is not a reply to our request
939
940		// TODO: log this event
941		gBufferModule->free(packet);
942		return;
943	}
944
945	// parse this ack
946	KPPPConfigurePacket ack(packet);
947	ppp_configure_item *item;
948	in_addr_t *requestedAddress, *wishedAddress = NULL, *configuredAddress = NULL;
949	for (int32 index = 0; index < ack.CountItems(); index++) {
950		item = ack.ItemAt(index);
951		if (!item)
952			continue;
953
954		// addresses have special handling to reduce code size
955		switch (item->type) {
956			case IPCP_ADDRESSES:
957				// abandoned by the standard
958			case IPCP_ADDRESS:
959				wishedAddress = &fLocalRequests.address;
960				configuredAddress = &fLocalConfiguration.address;
961			break;
962
963			case IPCP_PRIMARY_DNS:
964				wishedAddress = &fLocalRequests.primaryDNS;
965				configuredAddress = &fLocalConfiguration.primaryDNS;
966			break;
967
968			case IPCP_SECONDARY_DNS:
969				wishedAddress = &fLocalRequests.secondaryDNS;
970				configuredAddress = &fLocalConfiguration.secondaryDNS;
971			break;
972		}
973
974		// now parse item
975		switch (item->type) {
976			case IPCP_ADDRESSES:
977				// abandoned by the standard
978			case IPCP_ADDRESS:
979			case IPCP_PRIMARY_DNS:
980			case IPCP_SECONDARY_DNS:
981				requestedAddress = (in_addr_t*) item->data;
982				if ((*wishedAddress == INADDR_ANY && *requestedAddress != INADDR_ANY)
983						|| *wishedAddress == *requestedAddress)
984					*configuredAddress = *requestedAddress;
985			break;
986
987//			case IPCP_COMPRESSION_PROTOCOL:
988				// TODO: implement me
989//			break;
990
991			default:
992				;
993		}
994	}
995
996	// if address was not specified we should select the given one
997	if (!ack.ItemWithType(IPCP_ADDRESS))
998		fLocalConfiguration.address = fLocalRequests.address;
999
1000
1001	switch (State()) {
1002		case PPP_INITIAL_STATE:
1003			IllegalEvent(PPP_RCA_EVENT);
1004		break;
1005
1006		case PPP_REQ_SENT_STATE:
1007			NewState(PPP_ACK_RCVD_STATE);
1008			InitializeRestartCount();
1009		break;
1010
1011		case PPP_ACK_RCVD_STATE:
1012			NewState(PPP_REQ_SENT_STATE);
1013			SendConfigureRequest();
1014		break;
1015
1016		case PPP_ACK_SENT_STATE:
1017			NewState(PPP_OPENED_STATE);
1018			InitializeRestartCount();
1019			ReportUpEvent();
1020		break;
1021
1022		case PPP_OPENED_STATE:
1023			NewState(PPP_REQ_SENT_STATE);
1024			SendConfigureRequest();
1025		break;
1026
1027		default:
1028			;
1029	}
1030
1031	gBufferModule->free(packet);
1032}
1033
1034
1035void
1036IPCP::RCNEvent(net_buffer *packet)
1037{
1038	TRACE("IPCP: RCNEvent() state=%d\n", State());
1039
1040	NetBufferHeaderReader<ppp_lcp_packet> bufferheader(packet);
1041	if (bufferheader.Status() != B_OK)
1042		return;
1043	ppp_lcp_packet &lcpHeader = bufferheader.Data();
1044
1045	if (fRequestID != lcpHeader.id) {
1046		// this packet is not a reply to our request
1047
1048		// TODO: log this event
1049		gBufferModule->free(packet);
1050		return;
1051	}
1052
1053	// parse this nak/reject
1054	KPPPConfigurePacket nak_reject(packet);
1055	ppp_configure_item *item;
1056	in_addr_t *requestedAddress;
1057	if (nak_reject.Code() == PPP_CONFIGURE_NAK)
1058		for (int32 index = 0; index < nak_reject.CountItems(); index++) {
1059			item = nak_reject.ItemAt(index);
1060			if (!item)
1061				continue;
1062
1063			switch (item->type) {
1064				case IPCP_ADDRESSES:
1065					// abandoned by the standard
1066				case IPCP_ADDRESS:
1067					if (item->length != 6)
1068						continue;
1069
1070					requestedAddress = (in_addr_t*) item->data;
1071					if (fLocalRequests.address == INADDR_ANY
1072							&& *requestedAddress != INADDR_ANY)
1073						fLocalConfiguration.address = *requestedAddress;
1074							// this will be used in our next request
1075				break;
1076
1077//				case IPCP_COMPRESSION_PROTOCOL:
1078					// TODO: implement me!
1079//				break;
1080
1081				case IPCP_PRIMARY_DNS:
1082					if (item->length != 6)
1083						continue;
1084
1085					requestedAddress = (in_addr_t*) item->data;
1086					if (fRequestPrimaryDNS
1087							&& fLocalRequests.primaryDNS == INADDR_ANY
1088							&& *requestedAddress != INADDR_ANY)
1089						fLocalConfiguration.primaryDNS = *requestedAddress;
1090							// this will be used in our next request
1091				break;
1092
1093				case IPCP_SECONDARY_DNS:
1094					if (item->length != 6)
1095						continue;
1096
1097					requestedAddress = (in_addr_t*) item->data;
1098					if (fRequestSecondaryDNS
1099							&& fLocalRequests.secondaryDNS == INADDR_ANY
1100							&& *requestedAddress != INADDR_ANY)
1101						fLocalConfiguration.secondaryDNS = *requestedAddress;
1102							// this will be used in our next request
1103				break;
1104
1105				default:
1106					;
1107			}
1108		}
1109	else if (nak_reject.Code() == PPP_CONFIGURE_REJECT)
1110		for (int32 index = 0; index < nak_reject.CountItems(); index++) {
1111			item = nak_reject.ItemAt(index);
1112			if (!item)
1113				continue;
1114
1115			switch (item->type) {
1116//				case IPCP_COMPRESSION_PROTOCOL:
1117					// TODO: implement me!
1118//				break;
1119
1120				default:
1121					// DNS and addresses must be supported if we set them to auto
1122					gBufferModule->free(packet);
1123					NewState(PPP_INITIAL_STATE);
1124					ReportUpFailedEvent();
1125					return;
1126			}
1127		}
1128
1129	switch (State()) {
1130		case PPP_INITIAL_STATE:
1131			IllegalEvent(PPP_RCN_EVENT);
1132		break;
1133
1134		case PPP_REQ_SENT_STATE:
1135		case PPP_ACK_SENT_STATE:
1136			InitializeRestartCount();
1137
1138		case PPP_ACK_RCVD_STATE:
1139		case PPP_OPENED_STATE:
1140			if (State() == PPP_ACK_RCVD_STATE || State() == PPP_OPENED_STATE)
1141				NewState(PPP_REQ_SENT_STATE);
1142			SendConfigureRequest();
1143		break;
1144
1145		default:
1146			;
1147	}
1148
1149	gBufferModule->free(packet);
1150}
1151
1152
1153void
1154IPCP::RTREvent(net_buffer *packet)
1155{
1156	TRACE("IPCP: RTREvent() state=%d\n", State());
1157
1158	NetBufferHeaderReader<ppp_lcp_packet> bufferheader(packet);
1159	if (bufferheader.Status() != B_OK)
1160		return;
1161	ppp_lcp_packet &lcpHeader = bufferheader.Data();
1162
1163	// we should not use the same ID as the peer
1164	if (fID == lcpHeader.id)
1165		fID -= 128;
1166
1167	switch (State()) {
1168		case PPP_INITIAL_STATE:
1169			IllegalEvent(PPP_RTR_EVENT);
1170		break;
1171
1172		case PPP_ACK_RCVD_STATE:
1173		case PPP_ACK_SENT_STATE:
1174			NewState(PPP_REQ_SENT_STATE);
1175
1176		case PPP_CLOSING_STATE:
1177		case PPP_REQ_SENT_STATE:
1178			SendTerminateAck(packet);
1179		return;
1180			// do not free packet
1181
1182		case PPP_OPENED_STATE:
1183			NewState(PPP_CLOSING_STATE);
1184			ResetRestartCount();
1185			SendTerminateAck(packet);
1186		return;
1187			// do not free packet
1188
1189		default:
1190			;
1191	}
1192
1193	gBufferModule->free(packet);
1194}
1195
1196
1197void
1198IPCP::RTAEvent(net_buffer *packet)
1199{
1200	TRACE("IPCP: RTAEvent() state=%d\n", State());
1201
1202	NetBufferHeaderReader<ppp_lcp_packet> bufferheader(packet);
1203	if (bufferheader.Status() != B_OK)
1204		return;
1205	ppp_lcp_packet &lcpHeader = bufferheader.Data();
1206	if (fTerminateID != lcpHeader.id) {
1207		// this packet is not a reply to our request
1208
1209		// TODO: log this event
1210		gBufferModule->free(packet);
1211		return;
1212	}
1213
1214	switch (State()) {
1215		case PPP_INITIAL_STATE:
1216			IllegalEvent(PPP_RTA_EVENT);
1217		break;
1218
1219		case PPP_CLOSING_STATE:
1220			NewState(PPP_INITIAL_STATE);
1221			ReportDownEvent();
1222		break;
1223
1224		case PPP_ACK_RCVD_STATE:
1225			NewState(PPP_REQ_SENT_STATE);
1226		break;
1227
1228		case PPP_OPENED_STATE:
1229			NewState(PPP_REQ_SENT_STATE);
1230			SendConfigureRequest();
1231		break;
1232
1233		default:
1234			;
1235	}
1236
1237	gBufferModule->free(packet);
1238}
1239
1240
1241void
1242IPCP::RUCEvent(net_buffer *packet)
1243{
1244	TRACE("IPCP: RUCEvent() state=%d\n", State());
1245
1246	SendCodeReject(packet);
1247}
1248
1249
1250void
1251IPCP::RXJBadEvent(net_buffer *packet)
1252{
1253	TRACE("IPCP: RXJBadEvent() state=%d\n", State());
1254
1255	switch (State()) {
1256		case PPP_INITIAL_STATE:
1257			IllegalEvent(PPP_RXJ_BAD_EVENT);
1258		break;
1259
1260		case PPP_CLOSING_STATE:
1261			NewState(PPP_INITIAL_STATE);
1262			ReportDownEvent();
1263		break;
1264
1265		case PPP_REQ_SENT_STATE:
1266		case PPP_ACK_RCVD_STATE:
1267		case PPP_ACK_SENT_STATE:
1268			NewState(PPP_INITIAL_STATE);
1269			ReportUpFailedEvent();
1270		break;
1271
1272		case PPP_OPENED_STATE:
1273			NewState(PPP_CLOSING_STATE);
1274			InitializeRestartCount();
1275			SendTerminateRequest();
1276		break;
1277
1278		default:
1279			;
1280	}
1281
1282	gBufferModule->free(packet);
1283}
1284
1285
1286// actions
1287void
1288IPCP::IllegalEvent(ppp_event event)
1289{
1290	// TODO: update error statistics
1291	ERROR("IPCP: IllegalEvent(event=%d) state=%d\n", event, State());
1292}
1293
1294
1295void
1296IPCP::ReportUpFailedEvent()
1297{
1298	// reset configurations
1299	memset(&fLocalConfiguration, 0, sizeof(ipcp_configuration));
1300	memset(&fPeerConfiguration, 0, sizeof(ipcp_configuration));
1301
1302	UpdateAddresses();
1303
1304	UpFailedEvent();
1305}
1306
1307
1308void
1309IPCP::ReportUpEvent()
1310{
1311	UpdateAddresses();
1312
1313	UpEvent();
1314}
1315
1316
1317void
1318IPCP::ReportDownEvent()
1319{
1320	// reset configurations
1321	memset(&fLocalConfiguration, 0, sizeof(ipcp_configuration));
1322	memset(&fPeerConfiguration, 0, sizeof(ipcp_configuration));
1323
1324	// don't update address if connect on demand is enabled
1325	dprintf("ppp down, and leaving old address and rotues\n");
1326	// UpdateAddresses();
1327
1328	DownEvent();
1329}
1330
1331
1332void
1333IPCP::InitializeRestartCount()
1334{
1335	fRequestCounter = fMaxRequest;
1336	fTerminateCounter = fMaxTerminate;
1337	fNakCounter = fMaxNak;
1338}
1339
1340
1341void
1342IPCP::ResetRestartCount()
1343{
1344	fRequestCounter = 0;
1345	fTerminateCounter = 0;
1346	fNakCounter = 0;
1347}
1348
1349
1350bool
1351IPCP::SendConfigureRequest()
1352{
1353	TRACE("IPCP: SendConfigureRequest() state=%d\n", State());
1354
1355	--fRequestCounter;
1356	fNextTimeout = system_time() + kIPCPStateMachineTimeout;
1357
1358	KPPPConfigurePacket request(PPP_CONFIGURE_REQUEST);
1359	request.SetID(NextID());
1360	fRequestID = request.ID();
1361	ip_item ipItem;
1362	ipItem.length = 6;
1363
1364	// add address
1365	ipItem.type = IPCP_ADDRESS;
1366	if (fLocalRequests.address == INADDR_ANY)
1367		ipItem.address = (fLocalConfiguration.address);
1368	else
1369		ipItem.address =(fLocalRequests.address);
1370	request.AddItem((ppp_configure_item*) &ipItem);
1371
1372	TRACE("IPCP: SCR: confaddr=%X; reqaddr=%X; addr=%X\n",
1373		fLocalConfiguration.address, fLocalRequests.address,
1374		((ip_item*)request.ItemAt(0))->address);
1375
1376	// add primary DNS (if needed)
1377	if (fRequestPrimaryDNS && fLocalRequests.primaryDNS == INADDR_ANY) {
1378		ipItem.type = IPCP_PRIMARY_DNS;
1379		ipItem.address = fLocalConfiguration.primaryDNS;
1380			// at first this is 0.0.0.0, but a nak might have set it to a correct value
1381		request.AddItem((ppp_configure_item*) &ipItem);
1382	}
1383
1384	// add secondary DNS (if needed)
1385	if (fRequestSecondaryDNS && fLocalRequests.primaryDNS == INADDR_ANY) {
1386		ipItem.type = IPCP_SECONDARY_DNS;
1387		ipItem.address = fLocalConfiguration.secondaryDNS;
1388			// at first this is 0.0.0.0, but a nak might have set it to a correct value
1389		request.AddItem((ppp_configure_item*) &ipItem);
1390	}
1391
1392	// TODO: add VJC support
1393
1394	return Send(request.ToNetBuffer(Interface().MRU())) == B_OK;
1395}
1396
1397
1398bool
1399IPCP::SendConfigureAck(net_buffer *packet)
1400{
1401	TRACE("IPCP: SendConfigureAck() state=%d\n", State());
1402
1403	if (!packet)
1404		return false;
1405
1406	NetBufferHeaderReader<ppp_lcp_packet> bufferheader(packet);
1407	if (bufferheader.Status() != B_OK)
1408		return false;
1409	ppp_lcp_packet &lcpheader = bufferheader.Data();
1410	lcpheader.code = PPP_CONFIGURE_ACK;
1411
1412	bufferheader.Sync();
1413
1414	KPPPConfigurePacket ack(packet);
1415
1416	// verify items
1417	ppp_configure_item *item;
1418	in_addr_t *requestedAddress, *wishedAddress = NULL, *configuredAddress = NULL;
1419	for (int32 index = 0; index < ack.CountItems(); index++) {
1420		item = ack.ItemAt(index);
1421		if (!item)
1422			continue;
1423
1424		// addresses have special handling to reduce code size
1425		switch (item->type) {
1426			case IPCP_ADDRESSES:
1427				// abandoned by the standard
1428			case IPCP_ADDRESS:
1429				wishedAddress = &fPeerRequests.address;
1430				configuredAddress = &fPeerConfiguration.address;
1431			break;
1432
1433			case IPCP_PRIMARY_DNS:
1434				wishedAddress = &fPeerRequests.primaryDNS;
1435				configuredAddress = &fPeerConfiguration.primaryDNS;
1436			break;
1437
1438			case IPCP_SECONDARY_DNS:
1439				wishedAddress = &fPeerRequests.secondaryDNS;
1440				configuredAddress = &fPeerConfiguration.secondaryDNS;
1441			break;
1442		}
1443
1444		// now parse item
1445		switch (item->type) {
1446			case IPCP_ADDRESSES:
1447				// abandoned by the standard
1448			case IPCP_ADDRESS:
1449			case IPCP_PRIMARY_DNS:
1450			case IPCP_SECONDARY_DNS:
1451				requestedAddress = (in_addr_t*) item->data;
1452				if ((*wishedAddress == INADDR_ANY && *requestedAddress != INADDR_ANY)
1453						|| *wishedAddress == *requestedAddress)
1454					*configuredAddress = *requestedAddress;
1455			break;
1456
1457//			case IPCP_COMPRESSION_PROTOCOL:
1458				// TODO: implement me!
1459//			break;
1460
1461			default:
1462				;
1463		}
1464	}
1465
1466	// if address was not specified we should select the given one
1467	if (!ack.ItemWithType(IPCP_ADDRESS))
1468		fPeerConfiguration.address = fPeerRequests.address;
1469
1470	return Send(packet) == B_OK;
1471}
1472
1473
1474bool
1475IPCP::SendConfigureNak(net_buffer *packet)
1476{
1477	TRACE("IPCP: SendConfigureNak() state=%d\n", State());
1478
1479	if (!packet)
1480		return false;
1481
1482	NetBufferHeaderReader<ppp_lcp_packet> bufferheader(packet);
1483	if (bufferheader.Status() != B_OK)
1484		return false;
1485
1486	ppp_lcp_packet &nak = bufferheader.Data();
1487
1488	if (nak.code == PPP_CONFIGURE_NAK) {
1489		if (fNakCounter == 0) {
1490			// We sent enough naks. Let's try a reject.
1491			nak.code = PPP_CONFIGURE_REJECT;
1492		} else
1493			--fNakCounter;
1494	}
1495
1496	bufferheader.Sync();
1497
1498	return Send(packet) == B_OK;
1499}
1500
1501
1502bool
1503IPCP::SendTerminateRequest()
1504{
1505	TRACE("IPCP: SendTerminateRequest() state=%d\n", State());
1506
1507	--fTerminateCounter;
1508	fNextTimeout = system_time() + kIPCPStateMachineTimeout;
1509
1510	net_buffer *packet = gBufferModule->create(256);
1511	if (!packet)
1512		return false;
1513
1514	ppp_lcp_packet *request;
1515	status_t status = gBufferModule->append_size(packet, 1492, (void **)(&request));
1516	if (status != B_OK)
1517		return false;
1518
1519	request->code = PPP_TERMINATE_REQUEST;
1520	request->id = fTerminateID = NextID();
1521	request->length = htons(4);
1522
1523	status = gBufferModule->trim(packet, 4);
1524	if (status != B_OK)
1525		return false;
1526
1527	return Send(packet) == B_OK;
1528}
1529
1530
1531bool
1532IPCP::SendTerminateAck(net_buffer *request)
1533{
1534	TRACE("IPCP: SendTerminateAck() state=%d\n", State());
1535
1536	net_buffer *reply = request;
1537
1538	if (!reply) {
1539		reply = gBufferModule->create(256);
1540		ppp_lcp_packet *ack;
1541		status_t status = gBufferModule->append_size(reply, 1492, (void **)(&ack));
1542		if (status != B_OK) {
1543			gBufferModule->free(reply);
1544			return false;
1545		}
1546		ack->id = NextID();
1547		ack->code = PPP_TERMINATE_ACK;
1548		ack->length = htons(4);
1549		gBufferModule->trim(reply, 4);
1550	} else {
1551		NetBufferHeaderReader<ppp_lcp_packet> bufferHeader(reply);
1552		if (bufferHeader.Status() < B_OK)
1553			return false;
1554		ppp_lcp_packet &ack = bufferHeader.Data();
1555		ack.code = PPP_TERMINATE_ACK;
1556		ack.length = htons(4);
1557	}
1558
1559	return Send(reply) == B_OK;
1560}
1561
1562
1563bool
1564IPCP::SendCodeReject(net_buffer *packet)
1565{
1566	TRACE("IPCP: SendCodeReject() state=%d\n", State());
1567
1568	if (!packet)
1569		return false;
1570
1571	NetBufferPrepend<ppp_lcp_packet> bufferHeader(packet);
1572	if (bufferHeader.Status() != B_OK)
1573		return false;
1574
1575	ppp_lcp_packet &reject = bufferHeader.Data();
1576
1577	reject.code = PPP_CODE_REJECT;
1578	reject.id = NextID();
1579	reject.length = htons(packet->size);
1580
1581	bufferHeader.Sync();
1582
1583	return Send(packet) == B_OK;
1584}
1585