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