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