GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/npppd/npppd/ccp.c Lines: 0 93 0.0 %
Date: 2017-11-13 Branches: 0 46 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: ccp.c,v 1.7 2015/12/05 18:43:36 mmcc 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 file provides functions for CCP (Compression Control Protocol).
30
 * MPPE is supported as a CCP option.
31
 * $Id: ccp.c,v 1.7 2015/12/05 18:43:36 mmcc Exp $
32
 */
33
#include <sys/types.h>
34
#include <sys/socket.h>
35
#include <sys/time.h>
36
#include <net/if_dl.h>
37
#include <netinet/in.h>
38
#include <stdlib.h>
39
#include <stdio.h>
40
#include <syslog.h>
41
#include <string.h>
42
#include <event.h>
43
44
#include "slist.h"
45
#include "npppd.h"
46
#include "fsm.h"
47
48
#ifdef	CCP_DEBUG
49
#define	CCPDEBUG(x)	fsm_log(x)
50
#define	CCP_ASSERT(x)	ASSERT(x)
51
#else
52
#define	CCPDEBUG(x)
53
#define	CCP_ASSERT(x)
54
#endif
55
56
static int   ccp_reqci (fsm *, u_char *, int *, int);
57
static void  ccp_open (fsm *);
58
static void  ccp_close (fsm *);
59
static void  ccp_start (fsm *);
60
static void  ccp_stop (fsm *);
61
static void  ccp_resetci (fsm *);
62
static int   ccp_cilen (fsm *);
63
static void  ccp_addci (fsm *, u_char *, int *);
64
static int   ccp_ackci (fsm *, u_char *, int);
65
static int   ccp_rejci (fsm *, u_char *, int);
66
static int   ccp_nakci (fsm *, u_char *, int);
67
static int   ccp_nackackci (fsm *, u_char *, int, int, int);
68
static int   ccp_ext (fsm *, int, int, u_char *, int);
69
70
static struct fsm_callbacks ccp_callbacks = {
71
	.cilen		= ccp_cilen,
72
	.resetci	= ccp_resetci,
73
	.addci		= ccp_addci,
74
	.ackci		= ccp_ackci,
75
	.nakci		= ccp_nakci,
76
	.rejci		= ccp_rejci,
77
	.reqci		= ccp_reqci,
78
	.up		= ccp_open,
79
	.down		= ccp_close,
80
	.starting	= ccp_start,
81
	.finished	= ccp_stop,
82
	.extcode	= ccp_ext,
83
	.proto_name	= "ccp",
84
};
85
86
/** Initialize the context for ccp */
87
void
88
ccp_init(ccp *_this, npppd_ppp *ppp)
89
{
90
	struct tunnconf *conf;
91
92
	memset(_this, 0, sizeof(ccp));
93
94
	_this->ppp = ppp;
95
	_this->fsm.callbacks = &ccp_callbacks;
96
	_this->fsm.protocol = PPP_PROTO_NCP | NCP_CCP;
97
	_this->fsm.ppp = ppp;
98
99
	fsm_init(&_this->fsm);
100
101
	conf = ppp_get_tunnconf(ppp);
102
	PPP_FSM_CONFIG(&_this->fsm, timeouttime, conf->ccp_timeout);
103
	PPP_FSM_CONFIG(&_this->fsm, maxconfreqtransmits,
104
	    conf->ccp_max_configure);
105
	PPP_FSM_CONFIG(&_this->fsm, maxtermtransmits,
106
	    conf->ccp_max_terminate);
107
	PPP_FSM_CONFIG(&_this->fsm, maxnakloops,
108
	    conf->ccp_max_nak_loop);
109
}
110
111
/** Request Command Interpreter */
112
static int
113
ccp_reqci(fsm *f, u_char *pktp, int *lpktp, int reject_if_disagree)
114
{
115
	int type, len, rcode, lrej, lnak;
116
	u_char *rejbuf, *nakbuf, *nakbuf0, *pktp0;
117
#ifdef USE_NPPPD_MPPE
118
	uint32_t peer_bits, our_bits;
119
#endif
120
	npppd_ppp *ppp;
121
122
	ppp = f->ppp;
123
124
	rejbuf = NULL;
125
	rcode = CONFACK;
126
	pktp0 = pktp;
127
	lrej = 0;
128
	lnak = 0;
129
130
	if ((rejbuf = malloc(*lpktp)) == NULL) {
131
		return rcode;
132
	}
133
	if ((nakbuf0 = malloc(*lpktp)) == NULL) {
134
		free(rejbuf);
135
		return rcode;
136
	}
137
	nakbuf = nakbuf0;
138
#define	remlen()	(*lpktp - (pktp - pktp0))
139
140
	while (remlen() >= 2) {
141
		GETCHAR(type, pktp);
142
		GETCHAR(len, pktp);
143
		if (len <= 0 || remlen() + 2 < len)
144
			goto fail;
145
146
		switch (type) {
147
#ifdef USE_NPPPD_MPPE
148
		case CCP_MPPE:
149
			if (len < 6)
150
				goto fail;
151
152
			if (ppp->mppe.enabled == 0)
153
				goto reject;
154
			GETLONG(peer_bits, pktp);
155
			our_bits = mppe_create_our_bits(&ppp->mppe, peer_bits);
156
			if (our_bits != peer_bits) {
157
				if (reject_if_disagree) {
158
					pktp -= 4;
159
					goto reject;
160
				}
161
				if (lrej > 0) {
162
				/* don't nak because we are doing rej */
163
				} else {
164
					PUTCHAR(type, nakbuf);
165
					PUTCHAR(6, nakbuf);
166
					PUTLONG(our_bits, nakbuf);
167
					rcode = CONFNAK;
168
				}
169
			} else
170
				ppp->ccp.mppe_p_bits = our_bits;
171
			break;
172
reject:
173
#endif
174
		default:
175
			pktp -= 2;
176
			memcpy(rejbuf + lrej, pktp, len);
177
			lrej += len;
178
			pktp += len;
179
			rcode = CONFREJ;
180
		}
181
		continue;
182
	}
183
fail:
184
	switch (rcode) {
185
	case CONFREJ:
186
		memcpy(pktp0, rejbuf, lrej);
187
		*lpktp = lrej;
188
		break;
189
	case CONFNAK:
190
		len = nakbuf - nakbuf0;
191
		memcpy(pktp0, nakbuf0, len);
192
		*lpktp = len;
193
		break;
194
	}
195
	free(rejbuf);
196
	free(nakbuf0);
197
198
	return rcode;
199
#undef	remlen
200
}
201
202
static void
203
ccp_open(fsm *f)
204
{
205
	ppp_ccp_opened(f->ppp);
206
}
207
208
static void
209
ccp_close(fsm *f)
210
{
211
}
212
213
static void
214
ccp_start(fsm *f)
215
{
216
}
217
218
static void
219
ccp_stop(fsm *f)
220
{
221
#ifdef USE_NPPPD_MPPE
222
	fsm_log(f, LOG_INFO, "CCP is stopped");
223
	ppp_ccp_stopped(f->ppp);
224
#endif
225
}
226
227
static void
228
ccp_resetci(fsm *f)
229
{
230
#ifdef	USE_NPPPD_MPPE
231
	if (f->ppp->mppe_started == 0)
232
		f->ppp->ccp.mppe_o_bits =
233
		    mppe_create_our_bits(&f->ppp->mppe, 0);
234
	/* don't reset if the ccp is started. */
235
#endif
236
}
237
238
static int
239
ccp_cilen(fsm *f)
240
{
241
	return f->ppp->mru;
242
}
243
244
/** Create a Confugre-Request */
245
static void
246
ccp_addci(fsm *f, u_char *pktp, int *lpktp)
247
{
248
	u_char *pktp0;
249
250
	pktp0 = pktp;
251
252
	if (f->ppp->ccp.mppe_rej == 0) {
253
		PUTCHAR(CCP_MPPE, pktp);
254
		PUTCHAR(6, pktp);
255
		PUTLONG(f->ppp->ccp.mppe_o_bits, pktp);
256
257
		*lpktp = pktp - pktp0;
258
	} else
259
		*lpktp = 0;
260
}
261
262
static int
263
ccp_ackci(fsm *f, u_char *pktp, int lpkt)
264
{
265
	return ccp_nackackci(f, pktp, lpkt, 0, 0);
266
}
267
268
269
static int
270
ccp_nakci(fsm *f, u_char *pktp, int lpkt)
271
{
272
	return ccp_nackackci(f, pktp, lpkt, 1, 0);
273
}
274
275
static int
276
ccp_rejci(fsm *f, u_char *pktp, int lpkt)
277
{
278
	return ccp_nackackci(f, pktp, lpkt, 0, 1);
279
}
280
281
static int
282
ccp_nackackci(fsm *f, u_char *pktp, int lpkt, int is_nak, int is_rej)
283
{
284
	int type, len;
285
	u_char *pktp0;
286
#ifdef	USE_NPPPD_MPPE
287
	uint32_t peer_bits, our_bits;
288
#endif
289
	npppd_ppp *ppp;
290
291
	ppp = f->ppp;
292
293
	pktp0 = pktp;
294
295
#define	remlen()	(lpkt - (pktp - pktp0))
296
	while (remlen() >= 2) {
297
		GETCHAR(type, pktp);
298
		GETCHAR(len, pktp);
299
		if (len <= 0 || remlen() + 2 < len)
300
			goto fail;
301
302
		switch (type) {
303
#ifdef USE_NPPPD_MPPE
304
		case CCP_MPPE:
305
			if (len < 6)
306
				goto fail;
307
			if (is_rej) {
308
				f->ppp->ccp.mppe_rej = 1;
309
				return 1;
310
			}
311
			if (ppp->mppe_started != 0) {
312
				/* resend silently */
313
				return 1;
314
			}
315
			GETLONG(peer_bits, pktp);
316
			/*
317
			 * With Yamaha RTX-1000 that is configured as
318
			 * "ppp ccp mppe-any",
319
			 *
320
			 *	npppd ConfReq (40,56,128) => RTX 1000
321
			 *	npppd <= (40,128) ConfNAK    RTX 1000
322
			 *	npppd ConfReq (40,56,128) => RTX 1000
323
			 *	npppd <= (40,128) ConfNAK    RTX 1000
324
			 *
325
			 * both peers never decide the final bits.  We insist
326
			 * the longest bit if our request is nacked.
327
			 */
328
			our_bits = mppe_create_our_bits(&ppp->mppe, peer_bits);
329
			if (peer_bits == our_bits || is_nak)
330
				ppp->ccp.mppe_o_bits = our_bits;
331
332
			break;
333
#endif
334
		default:
335
			goto fail;
336
		}
337
	}
338
	return 1;
339
fail:
340
	return 0;
341
}
342
343
#define	RESET_REQ	0x0e
344
#define	RESET_ACK	0x0f
345
346
static int
347
ccp_ext(fsm *f, int code, int id, u_char *pktp, int lpktp)
348
{
349
	switch (code) {
350
	case RESET_REQ:
351
		fsm_log(f, LOG_DEBUG, "Received ResetReq %d", id);
352
#ifdef USE_NPPPD_MPPE
353
		mppe_recv_ccp_reset(&f->ppp->mppe);
354
#endif
355
		/*
356
		 * RFC 3078 says MPPE can be synchronized without Reset-Ack,
357
		 * but it doesn't tell about necessity of Reset-Ack.  But
358
		 * in fact, windows peer will complain Reset-Ack with
359
		 * Code-Reject.  So we don't send Reset-Ack.
360
		 */
361
		return 1;
362
	case RESET_ACK:
363
		fsm_log(f, LOG_DEBUG, "Received ResetAck %d", id);
364
		return 1;
365
	}
366
	return 0;
367
}