GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/npppd/npppd/../pppoe/pppoe_session.c Lines: 0 210 0.0 %
Date: 2017-11-07 Branches: 0 68 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: pppoe_session.c,v 1.11 2015/12/05 16:10:31 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
29
/**@file
30
 * Session management of PPPoE protocol
31
 * $Id: pppoe_session.c,v 1.11 2015/12/05 16:10:31 yasuoka Exp $
32
 */
33
34
#include <sys/types.h>
35
#include <sys/socket.h>
36
#include <sys/uio.h>
37
#include <netinet/in.h>
38
#include <net/if.h>
39
#if defined(__NetBSD__)
40
#include <net/if_ether.h>
41
#else
42
#include <netinet/if_ether.h>
43
#endif
44
#include <net/if_dl.h>
45
#include <time.h>
46
#include <string.h>
47
#include <stdlib.h>
48
#include <stdio.h>
49
#include <event.h>
50
#include <syslog.h>
51
#include <stdarg.h>
52
53
#include "hash.h"
54
#include "slist.h"
55
#include "debugutil.h"
56
#include "bytebuf.h"
57
#include "pppoe.h"
58
#include "pppoe_local.h"
59
60
#include "npppd.h"
61
#include "ppp.h"
62
63
#ifdef	PPPOE_SESSION_DEBUG
64
#define	PPPOE_SESSION_ASSERT(x)	ASSERT(x)
65
#define	PPPOE_SESSION_DBG(x)	pppoe_session_log x
66
#else
67
#define	PPPOE_SESSION_ASSERT(x)
68
#define	PPPOE_SESSION_DBG(x)
69
#endif
70
71
#define	pppoed_listener_this(sess)					\
72
	((pppoed_listener *)slist_get(&(sess)->pppoed->listener, 	\
73
	    (sess)->listener_index))
74
75
static void  pppoe_session_log (pppoe_session *, int, const char *, ...) __printflike(3,4);
76
static int   pppoe_session_send_PADS (pppoe_session *, struct pppoe_tlv *,
77
    struct pppoe_tlv *);
78
static int   pppoe_session_send_PADT (pppoe_session *);
79
static int   pppoe_session_ppp_output (npppd_ppp *, u_char *, int, int);
80
static void  pppoe_session_close_by_ppp(npppd_ppp *);
81
static int   pppoe_session_bind_ppp (pppoe_session *);
82
static void  pppoe_session_dispose_event(int, short, void *);
83
84
/* Initialize PPPoE session context */
85
int
86
pppoe_session_init(pppoe_session *_this, pppoed *_pppoed, int idx,
87
    int session_id, u_char *ether_addr)
88
{
89
	memset(_this, 0, sizeof(pppoe_session));
90
91
	_this->pppoed = _pppoed;
92
	_this->session_id = session_id;
93
	_this->listener_index = idx;
94
	memcpy(_this->ether_addr, ether_addr, ETHER_ADDR_LEN);
95
96
	memcpy(_this->ehdr.ether_dhost, ether_addr, ETHER_ADDR_LEN);
97
	memcpy(_this->ehdr.ether_shost, pppoe_session_sock_ether_addr(_this),
98
	    ETHER_ADDR_LEN);
99
100
	evtimer_set(&_this->ev_disposing, pppoe_session_dispose_event, _this);
101
102
	return 0;
103
}
104
105
/* Disconnect PPPoE session */
106
void
107
pppoe_session_disconnect(pppoe_session *_this)
108
{
109
	struct timeval tv;
110
111
	if (_this->state != PPPOE_SESSION_STATE_DISPOSING) {
112
		pppoe_session_send_PADT(_this);
113
114
		/* free process should be par event */
115
		timerclear(&tv);
116
		evtimer_add(&_this->ev_disposing, &tv);
117
		_this->state = PPPOE_SESSION_STATE_DISPOSING;
118
	}
119
	if (_this->ppp != NULL)
120
		ppp_phy_downed(_this->ppp);
121
}
122
123
/* Stop PPPoE session */
124
void
125
pppoe_session_stop(pppoe_session *_this)
126
{
127
	if (_this->state != PPPOE_SESSION_STATE_DISPOSING)
128
		pppoe_session_disconnect(_this);
129
130
}
131
132
/* Finish PPPoE session */
133
void
134
pppoe_session_fini(pppoe_session *_this)
135
{
136
	evtimer_del(&_this->ev_disposing);
137
}
138
139
/* call back function from event(3) */
140
static void
141
pppoe_session_dispose_event(int fd, short ev, void *ctx)
142
{
143
	pppoe_session *_this;
144
145
	_this = ctx;
146
	pppoed_pppoe_session_close_notify(_this->pppoed, _this);
147
}
148
149
/*
150
 * I/O
151
 */
152
void
153
pppoe_session_input(pppoe_session *_this, u_char *pkt, int lpkt)
154
{
155
	int rval;
156
	npppd_ppp *ppp;
157
158
	ppp = _this->ppp;
159
	if (_this->ppp == NULL)
160
		return;
161
162
	if (_this->state != PPPOE_SESSION_STATE_RUNNING)
163
		return;
164
165
	rval = ppp->recv_packet(ppp, pkt, lpkt, 0);
166
	if (_this->ppp == NULL)	/* ppp is freed */
167
		return;
168
169
	if (rval == 2) {
170
		/*
171
		 * Quit this function before statistics counter
172
		 * is processed when the packet will be processed by
173
		 * PIPEX. Because current NPPPD PPPOE implementation
174
		 * is recieving all packet from BPF even though the
175
		 * PIPEX will process it.
176
		 */
177
	} else if (rval != 0)  {
178
		ppp->ierrors++;
179
	} else {
180
		ppp->ipackets++;
181
		ppp->ibytes += lpkt;
182
	}
183
184
	return;
185
}
186
187
static int
188
pppoe_session_output(pppoe_session *_this, int is_disc, u_char *pkt,
189
    int lpkt)
190
{
191
	int sz, niov, tlen;
192
	struct iovec iov[4];
193
	struct pppoe_header pppoe0, *pppoe;
194
	char pad[ETHERMIN];
195
196
197
	niov = 0;
198
	tlen = 0;
199
	iov[niov].iov_base = &_this->ehdr;
200
	iov[niov++].iov_len = sizeof(_this->ehdr);
201
202
	if (is_disc) {
203
		_this->ehdr.ether_type = htons(ETHERTYPE_PPPOEDISC);
204
		iov[niov].iov_base = pkt;
205
		iov[niov++].iov_len = lpkt;
206
		pppoe = (struct pppoe_header *)pkt;
207
		pppoe->length = htons(lpkt - sizeof(pppoe0));
208
		tlen += lpkt;
209
	} else {
210
		_this->ehdr.ether_type = htons(ETHERTYPE_PPPOE);
211
		pppoe0.ver = PPPOE_RFC2516_VER;
212
		pppoe0.type = PPPOE_RFC2516_TYPE;
213
		pppoe0.code = 0;
214
		pppoe0.session_id = htons(_this->session_id);
215
		pppoe0.length = htons(lpkt);
216
		iov[niov].iov_base = &pppoe0;
217
		iov[niov++].iov_len = sizeof(pppoe0);
218
		tlen += sizeof(pppoe0);
219
		iov[niov].iov_base = pkt;
220
		iov[niov++].iov_len = lpkt;
221
		tlen += lpkt;
222
	}
223
	if (tlen < ETHERMIN) {
224
		memset(pad, 0, ETHERMIN - tlen);
225
		iov[niov].iov_base = pad;
226
		iov[niov++].iov_len = ETHERMIN - tlen;
227
	}
228
229
	sz = writev(pppoe_session_sock_bpf(_this), iov, niov);
230
231
	return (sz > 0)? 0 : -1;
232
}
233
234
static int
235
pppoe_session_send_PADT(pppoe_session *_this)
236
{
237
	u_char bufspace[2048];
238
	bytebuffer *buf;
239
	struct pppoe_header pppoe;
240
	int rval = 0;
241
	struct pppoe_tlv tlv;
242
243
	if ((buf = bytebuffer_wrap(bufspace, sizeof(bufspace))) == NULL) {
244
		pppoe_session_log(_this, LOG_ERR,
245
		"bytebuffer_wrap() failed on %s(): %m", __func__);
246
		return -1;
247
	}
248
	bytebuffer_clear(buf);
249
250
	/*
251
	 * PPPoE Header
252
	 */
253
	memset(&pppoe, 0, sizeof(pppoe));
254
	pppoe.ver = PPPOE_RFC2516_VER;
255
	pppoe.type = PPPOE_RFC2516_TYPE;
256
	pppoe.code = PPPOE_CODE_PADT;
257
	pppoe.session_id = htons(_this->session_id);
258
	bytebuffer_put(buf, &pppoe, sizeof(pppoe));
259
260
	/*
261
	 * Tag - End-of-List
262
	 */
263
	tlv.type = htons(PPPOE_TAG_END_OF_LIST);
264
	tlv.length = 0;
265
	bytebuffer_put(buf, &tlv, sizeof(tlv));
266
	tlv.type = htons(PPPOE_TAG_END_OF_LIST);
267
	tlv.length = 0;
268
	bytebuffer_put(buf, &tlv, sizeof(tlv));
269
270
	bytebuffer_flip(buf);
271
	if (pppoe_session_output(_this, 1, bytebuffer_pointer(buf),
272
	    bytebuffer_remaining(buf)) != 0) {
273
		pppoe_session_log(_this, LOG_ERR, "pppoed_output failed: %m");
274
		rval = 1;
275
	}
276
	pppoe_session_log(_this, LOG_INFO, "SendPADT");
277
278
	bytebuffer_unwrap(buf);
279
	bytebuffer_destroy(buf);
280
281
	return rval;
282
}
283
284
/* send PADS */
285
static int
286
pppoe_session_send_PADS(pppoe_session *_this, struct pppoe_tlv *hostuniq,
287
    struct pppoe_tlv *service_name)
288
{
289
	int rval, len;
290
	u_char bufspace[2048], msgbuf[80];
291
	bytebuffer *buf;
292
	struct pppoe_header pppoe;
293
	struct pppoe_tlv tlv;
294
295
	if ((buf = bytebuffer_wrap(bufspace, sizeof(bufspace))) == NULL) {
296
		pppoe_session_log(_this, LOG_ERR,
297
		"bytebuffer_wrap() failed on %s(): %m", __func__);
298
		return -1;
299
	}
300
	bytebuffer_clear(buf);
301
302
	/*
303
	 * PPPoE Header
304
	 */
305
	memset(&pppoe, 0, sizeof(pppoe));
306
	pppoe.ver = PPPOE_RFC2516_VER;
307
	pppoe.type = PPPOE_RFC2516_TYPE;
308
	pppoe.code = PPPOE_CODE_PADS;
309
	pppoe.session_id = htons(_this->session_id);
310
	bytebuffer_put(buf, &pppoe, sizeof(pppoe));
311
312
	/*
313
	 * Tag - Service-Name
314
	 */
315
	msgbuf[0] = '\0';
316
	if (service_name != NULL) {
317
		tlv.type = htons(PPPOE_TAG_SERVICE_NAME);
318
		tlv.length = htons(service_name->length);
319
		bytebuffer_put(buf, &tlv, sizeof(tlv));
320
321
		len = service_name->length;
322
		if (len > 0) {
323
			bytebuffer_put(buf, service_name->value, len);
324
			strlcpy(msgbuf, service_name->value,
325
			    MINIMUM(len + 1, sizeof(msgbuf)));
326
		}
327
	}
328
329
	/*
330
	 * Tag - Host-Uniq
331
	 */
332
	if (hostuniq != NULL) {
333
		tlv.type = htons(PPPOE_TAG_HOST_UNIQ);
334
		tlv.length = htons(hostuniq->length);
335
		bytebuffer_put(buf, &tlv, sizeof(tlv));
336
		bytebuffer_put(buf, hostuniq->value, hostuniq->length);
337
	}
338
	tlv.type = htons(PPPOE_TAG_END_OF_LIST);
339
	tlv.length = 0;
340
	bytebuffer_put(buf, &tlv, sizeof(tlv));
341
342
	bytebuffer_flip(buf);
343
	rval = 0;
344
	if (pppoe_session_output(_this, 1, bytebuffer_pointer(buf),
345
	    bytebuffer_remaining(buf)) != 0) {
346
		pppoe_session_log(_this, LOG_ERR, "pppoed_output failed: %m");
347
		rval = 1;
348
	}
349
	pppoe_session_log(_this, LOG_INFO, "SendPADS serviceName=%s "
350
	    "hostUniq=%s", msgbuf,
351
	    hostuniq? pppoed_tlv_value_string(hostuniq) : "none");
352
353
	bytebuffer_unwrap(buf);
354
	bytebuffer_destroy(buf);
355
356
	return rval;
357
}
358
359
/* process PADR from the peer */
360
int
361
pppoe_session_recv_PADR(pppoe_session *_this, slist *tag_list)
362
{
363
	pppoed *pppoed0 = _this->pppoed;
364
	struct pppoe_tlv *tlv, *hostuniq, *service_name, *ac_cookie;
365
366
	service_name = NULL;
367
	hostuniq = NULL;
368
	ac_cookie = NULL;
369
	for (slist_itr_first(tag_list); slist_itr_has_next(tag_list); ) {
370
		tlv = slist_itr_next(tag_list);
371
		if (tlv->type == PPPOE_TAG_HOST_UNIQ)
372
			hostuniq = tlv;
373
		if (tlv->type == PPPOE_TAG_SERVICE_NAME)
374
			service_name = tlv;
375
		if (tlv->type == PPPOE_TAG_AC_COOKIE)
376
			ac_cookie = tlv;
377
	}
378
379
	if (ac_cookie) {
380
		/* avoid a session which has already has cookie. */
381
		if (hash_lookup(pppoed0->acookie_hash,
382
		    (void *)ac_cookie->value) != NULL)
383
			goto fail;
384
385
		_this->acookie = *(uint32_t *)(ac_cookie->value);
386
		hash_insert(pppoed0->acookie_hash,
387
			(void *)(intptr_t)_this->acookie, _this);
388
	}
389
390
	if (pppoe_session_send_PADS(_this, hostuniq, service_name) != 0)
391
		goto fail;
392
393
	if (pppoe_session_bind_ppp(_this) != 0)
394
		goto fail;
395
396
	_this->state = PPPOE_SESSION_STATE_RUNNING;
397
	return 0;
398
fail:
399
	return -1;
400
}
401
402
/* process PADT from the peer */
403
int
404
pppoe_session_recv_PADT(pppoe_session *_this, slist *tag_list)
405
{
406
	pppoe_session_log(_this, LOG_INFO, "RecvPADT");
407
408
	pppoe_session_stop(_this);
409
	_this->state = PPPOE_SESSION_STATE_DISPOSING;
410
411
	return 0;
412
}
413
414
/*
415
 * Log
416
 */
417
static void
418
pppoe_session_log(pppoe_session *_this, int prio, const char *fmt, ...)
419
{
420
	char logbuf[BUFSIZ];
421
	va_list ap;
422
423
	PPPOE_SESSION_ASSERT(_this != NULL);
424
	va_start(ap, fmt);
425
#ifdef	PPPOED_MULTIPLE
426
	snprintf(logbuf, sizeof(logbuf), "pppoed id=%u session=%d %s",
427
	    _this->pppoed->id, _this->session_id, fmt);
428
#else
429
	snprintf(logbuf, sizeof(logbuf), "pppoed if=%s session=%d %s",
430
	    pppoe_session_listen_ifname(_this), _this->session_id, fmt);
431
#endif
432
	vlog_printf(prio, logbuf, ap);
433
	va_end(ap);
434
}
435
436
/*
437
 * PPP
438
 */
439
static int
440
pppoe_session_ppp_output(npppd_ppp *ppp, u_char *pkt, int lpkt, int flag)
441
{
442
	int rval;
443
	pppoe_session *_this;
444
445
	_this = ppp->phy_context;
446
447
	rval = pppoe_session_output(_this, 0, pkt, lpkt);
448
449
	if (_this->ppp == NULL)		/* ppp is freed */
450
		return 0;
451
452
	if (rval != 0) {
453
		ppp->oerrors++;
454
	} else {
455
		ppp->opackets++;
456
		ppp->obytes += lpkt;
457
	}
458
459
	return 0;
460
}
461
462
static void
463
pppoe_session_close_by_ppp(npppd_ppp *ppp)
464
{
465
	pppoe_session *_this;
466
467
	_this = ppp->phy_context;
468
	PPPOE_SESSION_ASSERT(_this != NULL);
469
	if (_this != NULL)
470
		/* do this before pptp_call_disconnect() */
471
		_this->ppp = NULL;
472
473
	pppoe_session_disconnect(_this);
474
}
475
476
/* bind for PPP */
477
static int
478
pppoe_session_bind_ppp(pppoe_session *_this)
479
{
480
	int len;
481
	npppd_ppp *ppp;
482
	struct sockaddr_dl sdl;
483
484
	ppp = NULL;
485
	if ((ppp = ppp_create()) == NULL)
486
		goto fail;
487
488
	PPPOE_SESSION_ASSERT(_this->ppp == NULL);
489
490
	if (_this->ppp != NULL)
491
		return -1;
492
493
	_this->ppp = ppp;
494
495
	ppp->tunnel_type = NPPPD_TUNNEL_PPPOE;
496
	ppp->tunnel_session_id = _this->session_id;
497
	ppp->phy_context = _this;
498
	ppp->send_packet = pppoe_session_ppp_output;
499
	ppp->phy_close = pppoe_session_close_by_ppp;
500
501
	strlcpy(ppp->phy_label, PPPOE_SESSION_LISTENER_TUN_NAME(_this),
502
	    sizeof(ppp->phy_label));
503
504
	memset(&sdl, 0, sizeof(sdl));
505
	sdl.sdl_len = sizeof(sdl);
506
	sdl.sdl_family = AF_LINK;
507
	sdl.sdl_index = if_nametoindex(pppoe_session_listen_ifname(_this));
508
	len = strlen(pppoe_session_listen_ifname(_this));
509
	memcpy(sdl.sdl_data, pppoe_session_listen_ifname(_this), len);
510
	sdl.sdl_nlen = len;
511
	sdl.sdl_alen = ETHER_ADDR_LEN;
512
	memcpy(sdl.sdl_data + len, _this->ether_addr, ETHER_ADDR_LEN);
513
514
	memcpy(&ppp->phy_info.peer_dl, &sdl, sizeof(sdl));
515
516
	if (ppp_init(npppd_get_npppd(), ppp) != 0)
517
		goto fail;
518
	ppp->has_acf = 0;
519
520
521
	pppoe_session_log(_this, LOG_NOTICE, "logtype=PPPBind ppp=%d", ppp->id);
522
	ppp_start(ppp);
523
524
	return 0;
525
fail:
526
	pppoe_session_log(_this, LOG_ERR, "failed binding ppp");
527
528
	if (ppp != NULL)
529
		ppp_destroy(ppp);
530
	_this->ppp = NULL;
531
532
	return 1;
533
}