GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/npppd/npppd/ipcp.c Lines: 0 116 0.0 %
Date: 2017-11-07 Branches: 0 63 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: ipcp.c,v 1.5 2012/09/18 13:14:08 yasuoka Exp $ */
2
3
/*-
4
 * Copyright (c) 2009 Internet Initiative Japan Inc.
5
 * All rights reserved.
6
 *
7
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that the following conditions
9
 * are met:
10
 * 1. Redistributions of source code must retain the above copyright
11
 *    notice, this list of conditions and the following disclaimer.
12
 * 2. Redistributions in binary form must reproduce the above copyright
13
 *    notice, this list of conditions and the following disclaimer in the
14
 *    documentation and/or other materials provided with the distribution.
15
 *
16
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26
 * SUCH DAMAGE.
27
 */
28
/**@file
29
 * This is an implementation of IPCP. This code is currently implemented
30
 * as network service provider, and the peer is forced to obey our proposal.
31
 */
32
/*
33
 * RFC 1332, 1877
34
 */
35
/* $Id: ipcp.c,v 1.5 2012/09/18 13:14:08 yasuoka Exp $ */
36
#include <sys/types.h>
37
#include <sys/socket.h>
38
#include <sys/time.h>
39
#include <netinet/in.h>
40
#include <net/if_dl.h>
41
#include <arpa/inet.h>
42
#include <stdlib.h>
43
#include <stdio.h>
44
#include <syslog.h>
45
#include <string.h>
46
#include <event.h>
47
48
#include "debugutil.h"
49
#include "slist.h"
50
#include "npppd.h"
51
52
#ifdef	IPCP_DEBUG
53
#define	IPCP_DBG(x)	fsm_log x
54
#define	IPCP_ASSERT(x)	ASSERT(x)
55
#else
56
#define	IPCP_DBG(x)
57
#define	IPCP_ASSERT(x)
58
#endif
59
60
61
#define	IPCP_IP_ADDRESSES	1
62
#define	IPCP_IP_COMP		2
63
#define	IPCP_IP_ADDRESS		3
64
#define	IPCP_PRI_DNS		129	/* 0x81 */
65
#define	IPCP_PRI_NBNS		130	/* 0x82 */
66
#define	IPCP_SEC_DNS		131	/* 0x83 */
67
#define	IPCP_SEC_NBNS		132	/* 0x84 */
68
69
#define u32maskcmp(mask, a, b) (((a) & (mask)) == ((b) & (mask)))
70
71
static void  ipcp_resetci (fsm *);
72
static int   ipcp_cilen (fsm *);
73
static void  ipcp_addci (fsm *, u_char *, int *);
74
static int   ipcp_ackci (fsm *, u_char *, int);
75
static int   ipcp_nakci (fsm *, u_char *, int);
76
static int   ipcp_rejci (fsm *, u_char *, int);
77
static int   ipcp_reqci (fsm *, u_char *, int *, int);
78
static void  ipcp_open (fsm *);
79
static void  ipcp_close (fsm *);
80
static void  ipcp_start (fsm *);
81
static void  ipcp_stop (fsm *);
82
83
static struct fsm_callbacks ipcp_callbacks = {
84
	ipcp_resetci,	/* Reset our Configuration Information */
85
	ipcp_cilen,	/* Length of our Configuration Information */
86
	ipcp_addci,	/* Add our Configuration Information */
87
	ipcp_ackci,	/* ACK our Configuration Information */
88
	ipcp_nakci,	/* NAK our Configuration Information */
89
	ipcp_rejci,	/* Reject our Configuration Information */
90
	ipcp_reqci,	/* Request peer's Configuration Information */
91
92
	ipcp_open,	/* Called when fsm reaches OPENED state */
93
	ipcp_close,	/* Called when fsm leaves OPENED state */
94
	ipcp_start,	/* Called when we want the lower layer up */
95
	ipcp_stop,	/* Called when we want the lower layer down */
96
	NULL,		/* Called when Protocol-Reject received */
97
	NULL,		/* Retransmission is necessary */
98
	NULL,		/* Called to handle LCP-specific codes */
99
	"ipcp"		/* String name of protocol */
100
};
101
102
/**
103
 * Initialize {@link ::_ipcp IPCP instance }.
104
 */
105
void
106
ipcp_init(ipcp *_this, npppd_ppp *ppp)
107
{
108
	struct tunnconf *conf;
109
110
	memset(_this, 0, sizeof(ipcp));
111
112
	_this->ppp = ppp;
113
	_this->fsm.ppp = ppp;
114
115
	fsm_init(&_this->fsm);
116
117
	_this->fsm.callbacks = &ipcp_callbacks;
118
	_this->fsm.protocol = PPP_PROTO_NCP | NCP_IPCP;
119
120
	conf = ppp_get_tunnconf(ppp);
121
	PPP_FSM_CONFIG(&_this->fsm, timeouttime, conf->ipcp_timeout);
122
	PPP_FSM_CONFIG(&_this->fsm, maxconfreqtransmits,
123
	    conf->ipcp_max_configure);
124
	PPP_FSM_CONFIG(&_this->fsm, maxtermtransmits,
125
	    conf->ipcp_max_terminate);
126
	PPP_FSM_CONFIG(&_this->fsm, maxnakloops,
127
	    conf->ipcp_max_nak_loop);
128
}
129
130
static void
131
ipcp_resetci(fsm *f)
132
{
133
	IPCP_DBG((f, LOG_DEBUG, "%s", __func__));
134
	if (npppd_prepare_ip(f->ppp->pppd, f->ppp) != 0) {
135
		fsm_log(f, LOG_ERR, "failed to assign ip address.");
136
		ppp_stop(f->ppp, NULL);
137
	}
138
}
139
140
static int
141
ipcp_cilen(fsm *f)
142
{
143
	IPCP_DBG((f, LOG_DEBUG, "%s", __func__));
144
	return f->ppp->mru;
145
}
146
147
static void
148
ipcp_addci(fsm *f, u_char *pktp, int *lpktp)
149
{
150
	u_char *pktp0;
151
152
	IPCP_DBG((f, LOG_DEBUG, "%s", __func__));
153
	pktp0 = pktp;
154
155
	PUTCHAR(IPCP_IP_ADDRESS, pktp);
156
	PUTCHAR(6, pktp);
157
	memcpy(pktp, &f->ppp->ipcp.ip4_our.s_addr, 4);
158
	pktp += 4;
159
	*lpktp = pktp - pktp0;
160
}
161
162
163
static int
164
ipcp_ackci(fsm *f, u_char *pktp, int lpkt)
165
{
166
	IPCP_DBG((f, LOG_DEBUG, "%s", __func__));
167
	/* TODO */
168
	return -1;
169
}
170
171
static int
172
ipcp_nakci(fsm *f, u_char *pktp, int lpkt)
173
{
174
	IPCP_DBG((f, LOG_DEBUG, "%s", __func__));
175
176
	fsm_log(f, LOG_INFO, "Peer refused(ConfNak) our ip=%s.",
177
	    inet_ntoa(f->ppp->ipcp.ip4_our));
178
	fsm_close(f, NULL);
179
	return -1;
180
}
181
182
static int
183
ipcp_rejci(fsm *f, u_char *pktp, int lpkt)
184
{
185
	IPCP_DBG((f, LOG_DEBUG, "%s", __func__));
186
187
	fsm_log(f, LOG_INFO, "Peer refused(ConfRej) our ip=%s.",
188
	    inet_ntoa(f->ppp->ipcp.ip4_our));
189
	fsm_close(f, NULL);
190
191
	return 0;
192
}
193
194
static int
195
ipcp_reqci(fsm *f, u_char *pktp, int *lpktp, int reject_if_disagree)
196
{
197
	int type, len, rcode, lrej, lnak;
198
	u_char rejbuf0[256], nakbuf0[256], *nakbuf, *rejbuf, *pktp0;
199
	char buf0[256];
200
	struct in_addr ip_addr, *ip_addrp;
201
	npppd_ppp *ppp;
202
	npppd *_npppd;
203
	int ip_address_acked = 0;
204
205
	IPCP_DBG((f, LOG_DEBUG, "%s(reject_if_disagree=%d, nakloops=%d)",
206
	    __func__, reject_if_disagree, f->nakloops));
207
	ppp = f->ppp;
208
	_npppd = ppp->pppd;
209
210
	nakbuf = nakbuf0;
211
	rejbuf = rejbuf0;
212
	lrej = 0;
213
	lnak = 0;
214
	pktp0 = pktp;
215
	rcode = -1;
216
217
	if (*lpktp > 128) {
218
		rcode = CONFREJ;
219
		rejbuf = pktp;
220
		lrej = *lpktp;
221
		goto fail;
222
	}
223
224
#define	remlen()	(*lpktp - (pktp - pktp0))
225
226
	ip_address_acked = 0;
227
	while (remlen() >= 2) {
228
		GETCHAR(type, pktp);
229
		GETCHAR(len, pktp);
230
		if (len <= 0 || remlen() + 2 < len)
231
			goto fail;
232
233
		switch (type) {
234
		case IPCP_IP_ADDRESS:
235
		case IPCP_PRI_DNS:
236
		case IPCP_PRI_NBNS:
237
		case IPCP_SEC_DNS:
238
		case IPCP_SEC_NBNS:
239
			if (remlen() < 4)
240
				goto fail;
241
			GETLONG(ip_addr.s_addr, pktp);
242
			ip_addr.s_addr = htonl(ip_addr.s_addr);
243
244
			switch (type) {
245
			case IPCP_IP_ADDRESS:
246
				if (!ppp_ip_assigned(ppp)) {
247
					if (npppd_assign_ip_addr(ppp->pppd, ppp,
248
					    htonl(ip_addr.s_addr)) != 0 &&
249
					    npppd_assign_ip_addr(ppp->pppd, ppp,
250
					    INADDR_ANY) != 0) {
251
						/*
252
						 * The reason why it call with INADDR_ANY again here
253
						 * is to adapt the client expecting to fall back into
254
						 * dynamic allocation when user-select is allowed.
255
						 */
256
						pktp -= 4;
257
						goto do_reject;
258
					}
259
					strlcpy(buf0, inet_ntoa(ip_addr),
260
					    sizeof(buf0));
261
					fsm_log(f, LOG_INFO,
262
					    "IP Address peer=%s our=%s.", buf0,
263
					    inet_ntoa(
264
						ppp->ppp_framed_ip_address));
265
				}
266
267
				if (u32maskcmp(ppp->ppp_framed_ip_netmask
268
				    .s_addr, ip_addr.s_addr,
269
				    ppp->ppp_framed_ip_address.s_addr)) {
270
					/*
271
					 * In case of assigning network address, it obey
272
					 * peer's proposal if peer's IP-Address Option is
273
					 * included in network address to assign.
274
					 */
275
					ip_addrp = &ip_addr;
276
				} else {
277
					ip_addrp = &ppp->
278
					    ppp_framed_ip_address;
279
				}
280
				ip_address_acked = 1;
281
				break;
282
			case IPCP_PRI_DNS:
283
				ip_addrp = &ppp->ipcp.dns_pri;	break;
284
			case IPCP_SEC_DNS:
285
				ip_addrp = &ppp->ipcp.dns_sec;	break;
286
			case IPCP_PRI_NBNS:
287
				ip_addrp = &ppp->ipcp.nbns_pri;	break;
288
			case IPCP_SEC_NBNS:
289
				ip_addrp = &ppp->ipcp.nbns_sec;	break;
290
			default:
291
				ip_addrp = NULL;
292
			}
293
294
			if (ip_addrp == NULL ||
295
			    ip_addrp->s_addr == INADDR_NONE) {
296
				pktp -= 4;
297
				goto do_reject;
298
			}
299
			if (ip_addrp->s_addr != ip_addr.s_addr) {
300
				if (reject_if_disagree) {
301
					pktp -= 4;
302
					goto do_reject;
303
				}
304
				if (lrej > 0) {
305
				/* if there is a reject, will send Rej, not send Nak. */
306
				} else {
307
					PUTCHAR(type, nakbuf);
308
					PUTCHAR(6, nakbuf);
309
					PUTLONG(ntohl(ip_addrp->s_addr),
310
					    nakbuf);
311
					lnak += 6;
312
					rcode = CONFNAK;
313
				}
314
			}
315
			break;
316
		case IPCP_IP_COMP:
317
		case IPCP_IP_ADDRESSES:
318
		default:
319
			fsm_log(f, LOG_DEBUG, "Unhandled Option %02x %d", type,
320
			    len);
321
do_reject:
322
			pktp -= 2;
323
			memmove(rejbuf + lrej, pktp, len);
324
			lrej += len;
325
			pktp += len;
326
			rcode = CONFREJ;
327
		}
328
		continue;
329
	}
330
	if (rcode == -1)
331
		rcode = CONFACK;
332
333
fail:
334
	switch (rcode) {
335
	case CONFREJ:
336
		IPCP_DBG((f, LOG_DEBUG, "SendConfRej"));
337
		memmove(pktp0, rejbuf0, lrej);
338
		*lpktp = lrej;
339
		break;
340
	case CONFNAK:
341
		/*
342
		 * In case of Yamaha router is set "pp ppp ipcp ip-address off",
343
		 * it sends ConfReq without IP-Address Option.
344
		 * To quote RFC 1332:
345
		 * If negotiation about the remote IP-address is required, and
346
		 * the peer did not provide the option in its Configure-Request,
347
		 * the option SHOULD be appended to a Configure-Nak.
348
		 *
349
		 * Is any problem of overrunning 6 bytes of lpkt?
350
		 *  - In ppp.c, lpkt is allocated mru + 64 bytes. lpkt is less
351
		 *    than mru, so +6 is enough.
352
		 */
353
		if (!ip_address_acked) {
354
			/* It is mandatory to assign IP address. */
355
			if (!ppp_ip_assigned(ppp)) {
356
				if (npppd_assign_ip_addr(ppp->pppd, ppp,
357
				    INADDR_ANY) != 0) {
358
				    /* The log already put in npppd_assign_ip_addr(). */
359
				}
360
			}
361
			PUTCHAR(IPCP_IP_ADDRESS, nakbuf);
362
			PUTCHAR(6, nakbuf);
363
			PUTLONG(ntohl(ppp->ppp_framed_ip_address.s_addr),
364
			    nakbuf);
365
			lnak += 6;
366
		}
367
		IPCP_DBG((f, LOG_DEBUG, "SendConfNak"));
368
		memmove(pktp0, nakbuf0, lnak);
369
		*lpktp = lnak;
370
		break;
371
	case CONFACK:
372
		IPCP_DBG((f, LOG_DEBUG, "SendConfAck"));
373
		break;
374
	}
375
376
	return rcode;
377
#undef	remlen
378
}
379
380
static void
381
ipcp_open(fsm *f)
382
{
383
	if (!ppp_ip_assigned(f->ppp)) {
384
		fsm_log(f, LOG_INFO, "the ip-address option from the peer was "
385
		    "not agreed.");
386
		/*
387
		 * agreed without IP-Address Option.  try to assign static address.
388
		 */
389
		if (f->ppp->realm_framed_ip_address.s_addr
390
			    != INADDR_USER_SELECT &&
391
		    f->ppp->realm_framed_ip_address.s_addr
392
			    != INADDR_NAS_SELECT &&
393
		    f->ppp->realm_framed_ip_address.s_addr != 0) {
394
			npppd_assign_ip_addr(f->ppp->pppd, f->ppp, INADDR_ANY);
395
		}
396
	}
397
	if (!ppp_ip_assigned(f->ppp)) {
398
		fsm_log(f, LOG_NOTICE,
399
		    "IPCP opened but no IP address for the peer.");
400
		ppp_stop(f->ppp, NULL);
401
		return;
402
	}
403
404
	fsm_log(f, LOG_INFO, "logtype=Opened ip=%s assignType=%s",
405
	    inet_ntoa(f->ppp->ppp_framed_ip_address),
406
	    (f->ppp->assign_dynapool)? "dynamic" : "static");
407
408
	ppp_ipcp_opened(f->ppp);
409
}
410
411
static void
412
ipcp_close(fsm *f)
413
{
414
	IPCP_DBG((f, LOG_DEBUG, "%s", __func__));
415
}
416
417
static void
418
ipcp_start(fsm *f)
419
{
420
}
421
422
static void
423
ipcp_stop(fsm *f)
424
{
425
	fsm_log(f, LOG_INFO, "IPCP is stopped");
426
	ppp_stop(f->ppp, NULL);
427
}