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