xref: /haiku/src/add-ons/kernel/network/ppp/ipcp/Protocol.cpp (revision cd6365c7ce7802f3c93b0aa7bb10ed7ae01af1c6)
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 
36 extern net_buffer_module_info *gBufferModule;
37 static struct net_datalink_module_info *sDatalinkModule;
38 static struct net_stack_module_info *sStackModule;
39 
40 #if DEBUG
41 #include <unistd.h>
42 
43 static int sFD;
44 	// the file descriptor for debug output
45 static char sDigits[] = "0123456789ABCDEF";
46 void
dump_packet(net_buffer * packet,const char * direction)47 dump_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 
74 static const bigtime_t kIPCPStateMachineTimeout = 3000000;
75 	// 3 seconds
76 
77 
IPCP(KPPPInterface & interface,driver_parameter * settings)78 IPCP::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 
~IPCP()116 IPCP::~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 
127 void
Uninit()128 IPCP::Uninit()
129 {
130 	RemoveRoutes();
131 }
132 
133 
134 status_t
StackControl(uint32 op,void * data)135 IPCP::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 
164 bool
Up()165 IPCP::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 
189 bool
Down()190 IPCP::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 
230 status_t
Send(net_buffer * packet,uint16 protocolNumber)231 IPCP::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 
251 status_t
Receive(net_buffer * packet,uint16 protocolNumber)252 IPCP::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 
310 status_t
ReceiveIPPacket(net_buffer * packet,uint16 protocolNumber)311 IPCP::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 
335 void
Pulse()336 IPCP::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 
365 bool
ParseSideRequests(const driver_parameter * requests,ppp_side side)366 IPCP::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 
422 net_interface *
get_interface_by_name(net_domain * domain,const char * name)423 get_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 
439 status_t
set_interface_address(net_domain * domain,struct ifaliasreq * inreq)440 set_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 
447 void
UpdateAddresses()448 IPCP::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 
575 void
RemoveRoutes()576 IPCP::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 
648 uint8
NextID()649 IPCP::NextID()
650 {
651 	return (uint8) atomic_add(&fID, 1);
652 }
653 
654 
655 void
NewState(ppp_state next)656 IPCP::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 
674 void
TOGoodEvent()675 IPCP::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 
700 void
TOBadEvent()701 IPCP::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 
724 void
RCREvent(net_buffer * packet)725 IPCP::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 
834 void
RCRGoodEvent(net_buffer * packet)835 IPCP::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 
872 void
RCRBadEvent(net_buffer * nak,net_buffer * reject)873 IPCP::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 
928 void
RCAEvent(net_buffer * packet)929 IPCP::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 
1035 void
RCNEvent(net_buffer * packet)1036 IPCP::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 
1153 void
RTREvent(net_buffer * packet)1154 IPCP::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 
1197 void
RTAEvent(net_buffer * packet)1198 IPCP::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 
1241 void
RUCEvent(net_buffer * packet)1242 IPCP::RUCEvent(net_buffer *packet)
1243 {
1244 	TRACE("IPCP: RUCEvent() state=%d\n", State());
1245 
1246 	SendCodeReject(packet);
1247 }
1248 
1249 
1250 void
RXJBadEvent(net_buffer * packet)1251 IPCP::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
1287 void
IllegalEvent(ppp_event event)1288 IPCP::IllegalEvent(ppp_event event)
1289 {
1290 	// TODO: update error statistics
1291 	ERROR("IPCP: IllegalEvent(event=%d) state=%d\n", event, State());
1292 }
1293 
1294 
1295 void
ReportUpFailedEvent()1296 IPCP::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 
1308 void
ReportUpEvent()1309 IPCP::ReportUpEvent()
1310 {
1311 	UpdateAddresses();
1312 
1313 	UpEvent();
1314 }
1315 
1316 
1317 void
ReportDownEvent()1318 IPCP::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 
1332 void
InitializeRestartCount()1333 IPCP::InitializeRestartCount()
1334 {
1335 	fRequestCounter = fMaxRequest;
1336 	fTerminateCounter = fMaxTerminate;
1337 	fNakCounter = fMaxNak;
1338 }
1339 
1340 
1341 void
ResetRestartCount()1342 IPCP::ResetRestartCount()
1343 {
1344 	fRequestCounter = 0;
1345 	fTerminateCounter = 0;
1346 	fNakCounter = 0;
1347 }
1348 
1349 
1350 bool
SendConfigureRequest()1351 IPCP::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 
1398 bool
SendConfigureAck(net_buffer * packet)1399 IPCP::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 
1474 bool
SendConfigureNak(net_buffer * packet)1475 IPCP::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 
1502 bool
SendTerminateRequest()1503 IPCP::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 
1531 bool
SendTerminateAck(net_buffer * request)1532 IPCP::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 
1563 bool
SendCodeReject(net_buffer * packet)1564 IPCP::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