1 /*	$OpenBSD: pipex.c,v 1.158 2025/02/03 09:44:30 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 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/mbuf.h>
32 #include <sys/socket.h>
33 #include <sys/ioctl.h>
34 #include <sys/sysctl.h>
35 #include <sys/syslog.h>
36 #include <sys/conf.h>
37 #include <sys/time.h>
38 #include <sys/timeout.h>
39 #include <sys/kernel.h>
40 #include <sys/pool.h>
41 #include <sys/percpu.h>
42 #include <sys/mutex.h>
43 
44 #include <net/if.h>
45 #include <net/if_types.h>
46 #include <netinet/in.h>
47 #include <netinet/if_ether.h>
48 #include <net/if_dl.h>
49 
50 #include <net/radix.h>
51 #include <net/route.h>
52 #include <net/ppp_defs.h>
53 #include <net/ppp-comp.h>
54 #include <net/netisr.h>
55 
56 #include "pf.h"
57 #if NPF > 0
58 #include <net/pfvar.h>
59 #endif
60 
61 #include "bpfilter.h"
62 #if NBPFILTER > 0
63 #include <net/bpf.h>
64 #endif
65 
66 #include <netinet/ip.h>
67 #include <netinet/ip_var.h>
68 #ifdef INET6
69 #include <netinet/ip6.h>
70 #include <netinet6/ip6_var.h>
71 #endif
72 #include <netinet/tcp.h>
73 #include <netinet/udp.h>
74 #include <netinet/udp_var.h>
75 #include <crypto/arc4.h>
76 
77 #include <net/pipex.h>
78 #include "pipex_local.h"
79 
80 struct mutex pipex_list_mtx = MUTEX_INITIALIZER(IPL_SOFTNET);
81 
82 struct pool pipex_session_pool;
83 struct pool mppe_key_pool;
84 
85 /*
86  * Global data
87  * Locks used to protect global data
88  *       A       atomic operation
89  *       I       immutable after creation
90  *       L       pipex_list_mtx
91  */
92 
93 int	pipex_enable = 0;			/* [A] */
94 struct pipex_hash_head
95     pipex_session_list,				/* [L] master session list */
96     pipex_close_wait_list,			/* [L] expired session list */
97     pipex_peer_addr_hashtable[PIPEX_HASH_SIZE],	/* [L] peer's address hash */
98     pipex_id_hashtable[PIPEX_HASH_SIZE];	/* [L] peer id hash */
99 
100 struct radix_node_head	*pipex_rd_head4 = NULL;	/* [L] */
101 struct timeout pipex_timer_ch;		/* callout timer context */
102 int pipex_prune = 1;			/* [I] walk list every seconds */
103 
104 struct mbuf_queue pipexoutq = MBUF_QUEUE_INITIALIZER(
105     IFQ_MAXLEN, IPL_SOFTNET);
106 
107 #ifdef PIPEX_DEBUG
108 int pipex_debug = 0;		/* [A] systcl net.inet.ip.pipex_debug */
109 #endif
110 
111 /* PPP compression == MPPE is assumed, so don't answer CCP Reset-Request. */
112 #define PIPEX_NO_CCP_RESETACK	1
113 
114 /************************************************************************
115  * Core functions
116  ************************************************************************/
117 void
pipex_init(void)118 pipex_init(void)
119 {
120 	int		 i;
121 	static int	 pipex_init_done = 0;
122 
123 	if (pipex_init_done++)
124 		return;
125 
126 	rn_init(sizeof(struct sockaddr_in6));
127 
128 	pool_init(&pipex_session_pool, sizeof(struct pipex_session), 0,
129 	    IPL_SOFTNET, PR_WAITOK, "ppxss", NULL);
130 	pool_init(&mppe_key_pool, PIPEX_MPPE_KEYLEN * PIPEX_MPPE_NOLDKEY, 0,
131 	    IPL_SOFTNET, PR_WAITOK, "mppekey", NULL);
132 
133 	LIST_INIT(&pipex_session_list);
134 	LIST_INIT(&pipex_close_wait_list);
135 
136 	for (i = 0; i < nitems(pipex_id_hashtable); i++)
137 		LIST_INIT(&pipex_id_hashtable[i]);
138 	for (i = 0; i < nitems(pipex_peer_addr_hashtable); i++)
139 		LIST_INIT(&pipex_peer_addr_hashtable[i]);
140 }
141 
142 void
pipex_destroy_all_sessions(void * ownersc)143 pipex_destroy_all_sessions(void *ownersc)
144 {
145 	struct pipex_session *session, *session_tmp;
146 
147 	mtx_enter(&pipex_list_mtx);
148 
149 	LIST_FOREACH_SAFE(session, &pipex_session_list, session_list,
150 	    session_tmp) {
151 		if (session->flags & PIPEX_SFLAGS_ITERATOR)
152 			continue;
153 		if (session->ownersc == ownersc) {
154 			KASSERT((session->flags & PIPEX_SFLAGS_PPPX) == 0);
155 			pipex_unlink_session_locked(session);
156 			pipex_rele_session(session);
157 		}
158 	}
159 
160 	mtx_leave(&pipex_list_mtx);
161 }
162 
163 int
pipex_ioctl(void * ownersc,u_long cmd,caddr_t data)164 pipex_ioctl(void *ownersc, u_long cmd, caddr_t data)
165 {
166 	int ret = 0;
167 
168 	switch (cmd) {
169 	case PIPEXGSTAT:
170 		ret = pipex_get_stat((struct pipex_session_stat_req *)data,
171 		    ownersc);
172 		break;
173 
174 	case PIPEXGCLOSED:
175 		ret = pipex_get_closed((struct pipex_session_list_req *)data,
176 		    ownersc);
177 		break;
178 
179 	default:
180 		ret = ENOTTY;
181 		break;
182 	}
183 
184 	return (ret);
185 }
186 
187 /************************************************************************
188  * Software Interrupt Handler
189  ************************************************************************/
190 
191 void
pipexintr(void)192 pipexintr(void)
193 {
194 	struct mbuf_list ml;
195 	struct mbuf *m;
196 	struct pipex_session *session;
197 
198 	NET_ASSERT_LOCKED();
199 
200 	mq_delist(&pipexoutq, &ml);
201 
202 	while ((m = ml_dequeue(&ml)) != NULL) {
203 		struct ifnet *ifp;
204 
205 		session = m->m_pkthdr.ph_cookie;
206 
207 		ifp = if_get(session->proto.pppoe.over_ifidx);
208 		if (ifp != NULL) {
209 			struct pipex_pppoe_header *pppoe;
210 			int len;
211 
212 			pppoe = mtod(m, struct pipex_pppoe_header *);
213 			len = ntohs(pppoe->length);
214 			ifp->if_output(ifp, m, &session->peer.sa, NULL);
215 			counters_pkt(session->stat_counters, pxc_opackets,
216 			    pxc_obytes, len);
217 		} else {
218 			m_freem(m);
219 			counters_inc(session->stat_counters, pxc_oerrors);
220 		}
221 		if_put(ifp);
222 
223 		pipex_rele_session(session);
224 	}
225 }
226 
227 /************************************************************************
228  * Session management functions
229  ************************************************************************/
230 int
pipex_init_session(struct pipex_session ** rsession,struct pipex_session_req * req)231 pipex_init_session(struct pipex_session **rsession,
232     struct pipex_session_req *req)
233 {
234 	struct pipex_session *session;
235 #ifdef PIPEX_PPPOE
236 	struct ifnet *over_ifp = NULL;
237 #endif
238 
239 	/* Checks requested parameters.  */
240 	switch (req->pr_protocol) {
241 #ifdef PIPEX_PPPOE
242 	case PIPEX_PROTO_PPPOE:
243 		if (req->pr_peer_address.ss_family != AF_UNSPEC)
244 			return (EINVAL);
245 		break;
246 #endif
247 #if defined(PIPEX_L2TP) || defined(PIPEX_PPTP)
248 	case PIPEX_PROTO_PPTP:
249 	case PIPEX_PROTO_L2TP:
250 		switch (req->pr_peer_address.ss_family) {
251 		case AF_INET:
252 			if (req->pr_peer_address.ss_len !=
253 			    sizeof(struct sockaddr_in))
254 				return (EINVAL);
255 			break;
256 #ifdef INET6
257 		case AF_INET6:
258 			if (req->pr_peer_address.ss_len !=
259 			    sizeof(struct sockaddr_in6))
260 				return (EINVAL);
261 			break;
262 #endif
263 		default:
264 			return (EPROTONOSUPPORT);
265 		}
266 		if (req->pr_peer_address.ss_family !=
267 		    req->pr_local_address.ss_family ||
268 		    req->pr_peer_address.ss_len !=
269 		    req->pr_local_address.ss_len)
270 			return (EINVAL);
271 		break;
272 #endif /* defined(PIPEX_PPTP) || defined(PIPEX_L2TP) */
273 	default:
274 		return (EPROTONOSUPPORT);
275 	}
276 #ifdef PIPEX_MPPE
277 	if ((req->pr_ppp_flags & PIPEX_PPP_MPPE_ACCEPTED) != 0) {
278 		switch (req->pr_mppe_recv.keylenbits) {
279 		case 40:
280 		case 56:
281 		case 128:
282 			break;
283 		default:
284 			return (EINVAL);
285 		}
286 	}
287 	if ((req->pr_ppp_flags & PIPEX_PPP_MPPE_ENABLED) != 0) {
288 		switch (req->pr_mppe_send.keylenbits) {
289 		case 40:
290 		case 56:
291 		case 128:
292 			break;
293 		default:
294 			return (EINVAL);
295 		}
296 	}
297 	if ((req->pr_ppp_flags & PIPEX_PPP_MPPE_REQUIRED) != 0) {
298 		if ((req->pr_ppp_flags &
299 		    (PIPEX_PPP_MPPE_ACCEPTED | PIPEX_PPP_MPPE_ENABLED)) !=
300 		    (PIPEX_PPP_MPPE_ACCEPTED | PIPEX_PPP_MPPE_ENABLED))
301 			return (EINVAL);
302 	}
303 #endif
304 
305 #ifdef PIPEX_PPPOE
306 	if (req->pr_protocol == PIPEX_PROTO_PPPOE) {
307 		over_ifp = if_unit(req->pr_proto.pppoe.over_ifname);
308 		if (over_ifp == NULL)
309 			return (EINVAL);
310 	}
311 #endif
312 
313 	/* prepare a new session */
314 	session = pool_get(&pipex_session_pool, PR_WAITOK | PR_ZERO);
315 	refcnt_init(&session->pxs_refcnt);
316 	mtx_init(&session->pxs_mtx, IPL_SOFTNET);
317 	session->state = PIPEX_STATE_INITIAL;
318 	session->protocol = req->pr_protocol;
319 	session->session_id = req->pr_session_id;
320 	session->peer_session_id = req->pr_peer_session_id;
321 	session->peer_mru = req->pr_peer_mru;
322 	session->timeout_sec = req->pr_timeout_sec;
323 	session->ppp_flags = req->pr_ppp_flags;
324 	session->ppp_id = req->pr_ppp_id;
325 
326 	session->stat_counters = counters_alloc(pxc_ncounters);
327 
328 	session->ip_address.sin_family = AF_INET;
329 	session->ip_address.sin_len = sizeof(struct sockaddr_in);
330 	session->ip_address.sin_addr = req->pr_ip_address;
331 
332 	session->ip_netmask.sin_family = AF_INET;
333 	session->ip_netmask.sin_len = sizeof(struct sockaddr_in);
334 	session->ip_netmask.sin_addr = req->pr_ip_netmask;
335 
336 	if (session->ip_netmask.sin_addr.s_addr == 0L)
337 		session->ip_netmask.sin_addr.s_addr = 0xffffffffL;
338 	session->ip_address.sin_addr.s_addr &=
339 	    session->ip_netmask.sin_addr.s_addr;
340 
341 	if (req->pr_peer_address.ss_len > 0)
342 		memcpy(&session->peer, &req->pr_peer_address,
343 		    MIN(req->pr_peer_address.ss_len, sizeof(session->peer)));
344 	if (req->pr_local_address.ss_len > 0)
345 		memcpy(&session->local, &req->pr_local_address,
346 		    MIN(req->pr_local_address.ss_len, sizeof(session->local)));
347 #ifdef PIPEX_PPPOE
348 	if (req->pr_protocol == PIPEX_PROTO_PPPOE) {
349 		session->proto.pppoe.over_ifidx = over_ifp->if_index;
350 		if_put(over_ifp);
351 	}
352 #endif
353 #ifdef PIPEX_PPTP
354 	if (req->pr_protocol == PIPEX_PROTO_PPTP) {
355 		struct pipex_pptp_session *sess_pptp = &session->proto.pptp;
356 
357 		sess_pptp->snd_gap = 0;
358 		sess_pptp->rcv_gap = 0;
359 		sess_pptp->snd_una = req->pr_proto.pptp.snd_una;
360 		sess_pptp->snd_nxt = req->pr_proto.pptp.snd_nxt;
361 		sess_pptp->rcv_nxt = req->pr_proto.pptp.rcv_nxt;
362 		sess_pptp->rcv_acked = req->pr_proto.pptp.rcv_acked;
363 
364 		sess_pptp->winsz = req->pr_proto.pptp.winsz;
365 		sess_pptp->maxwinsz = req->pr_proto.pptp.maxwinsz;
366 		sess_pptp->peer_maxwinsz = req->pr_proto.pptp.peer_maxwinsz;
367 		/* last ack number */
368 		sess_pptp->ul_snd_una = sess_pptp->snd_una - 1;
369 	}
370 #endif
371 #ifdef PIPEX_L2TP
372 	if (req->pr_protocol == PIPEX_PROTO_L2TP) {
373 		struct pipex_l2tp_session *sess_l2tp = &session->proto.l2tp;
374 
375 		/* session keys */
376 		sess_l2tp->tunnel_id = req->pr_proto.l2tp.tunnel_id;
377 		sess_l2tp->peer_tunnel_id = req->pr_proto.l2tp.peer_tunnel_id;
378 
379 		/* protocol options */
380 		sess_l2tp->option_flags = req->pr_proto.l2tp.option_flags;
381 
382 		/* initial state of dynamic context */
383 		sess_l2tp->ns_gap = sess_l2tp->nr_gap = 0;
384 		sess_l2tp->ns_nxt = req->pr_proto.l2tp.ns_nxt;
385 		sess_l2tp->nr_nxt = req->pr_proto.l2tp.nr_nxt;
386 		sess_l2tp->ns_una = req->pr_proto.l2tp.ns_una;
387 		sess_l2tp->nr_acked = req->pr_proto.l2tp.nr_acked;
388 		/* last ack number */
389 		sess_l2tp->ul_ns_una = sess_l2tp->ns_una - 1;
390 		sess_l2tp->ipsecflowinfo = req->pr_proto.l2tp.ipsecflowinfo;
391 	}
392 #endif
393 #ifdef PIPEX_MPPE
394 	if ((req->pr_ppp_flags & PIPEX_PPP_MPPE_ACCEPTED) != 0) {
395 		pipex_session_init_mppe_recv(session,
396 		    req->pr_mppe_recv.stateless, req->pr_mppe_recv.keylenbits,
397 		    req->pr_mppe_recv.master_key);
398 	}
399 	if ((req->pr_ppp_flags & PIPEX_PPP_MPPE_ENABLED) != 0) {
400 		pipex_session_init_mppe_send(session,
401 		    req->pr_mppe_send.stateless, req->pr_mppe_send.keylenbits,
402 		    req->pr_mppe_send.master_key);
403 	}
404 #endif
405 
406 	*rsession = session;
407 
408 	return 0;
409 }
410 
411 void
pipex_rele_session(struct pipex_session * session)412 pipex_rele_session(struct pipex_session *session)
413 {
414 	if (refcnt_rele(&session->pxs_refcnt) == 0)
415 		return;
416 
417 	if (session->mppe_recv.old_session_keys)
418 		pool_put(&mppe_key_pool, session->mppe_recv.old_session_keys);
419 	counters_free(session->stat_counters, pxc_ncounters);
420 	pool_put(&pipex_session_pool, session);
421 }
422 
423 int
pipex_link_session(struct pipex_session * session,struct ifnet * ifp,void * ownersc)424 pipex_link_session(struct pipex_session *session, struct ifnet *ifp,
425     void *ownersc)
426 {
427 	struct pipex_hash_head *chain;
428 	struct radix_node *rn;
429 	int error = 0;
430 
431 	mtx_enter(&pipex_list_mtx);
432 
433 	if (pipex_rd_head4 == NULL) {
434 		if (!rn_inithead((void **)&pipex_rd_head4,
435 		    offsetof(struct sockaddr_in, sin_addr)))
436 			panic("rn_inithead() failed on pipex_link_session()");
437 	}
438 	if (pipex_lookup_by_session_id_locked(session->protocol,
439 	    session->session_id)) {
440 		error = EEXIST;
441 		goto out;
442 	}
443 
444 	session->ownersc = ownersc;
445 	session->ifindex = ifp->if_index;
446 	if (ifp->if_flags & IFF_POINTOPOINT)
447 		session->flags |= PIPEX_SFLAGS_PPPX;
448 
449 	if ((session->flags & PIPEX_SFLAGS_PPPX) == 0 &&
450 	    !in_nullhost(session->ip_address.sin_addr)) {
451 		if (pipex_lookup_by_ip_address_locked(
452 		    session->ip_address.sin_addr) != NULL) {
453 			error = EADDRINUSE;
454 			goto out;
455 		}
456 		rn = rn_addroute(&session->ip_address, &session->ip_netmask,
457 		    pipex_rd_head4, session->ps4_rn, RTP_STATIC);
458 		if (rn == NULL) {
459 			error = ENOMEM;
460 			goto out;
461 		}
462 	}
463 
464 	LIST_INSERT_HEAD(&pipex_session_list, session, session_list);
465 	chain = PIPEX_ID_HASHTABLE(session->session_id);
466 	LIST_INSERT_HEAD(chain, session, id_chain);
467 #if defined(PIPEX_PPTP) || defined(PIPEX_L2TP)
468 	switch (session->protocol) {
469 	case PIPEX_PROTO_PPTP:
470 	case PIPEX_PROTO_L2TP:
471 		chain = PIPEX_PEER_ADDR_HASHTABLE(
472 		    pipex_sockaddr_hash_key(&session->peer.sa));
473 		LIST_INSERT_HEAD(chain, session, peer_addr_chain);
474 	}
475 #endif
476 
477 	/* if first session is added, start timer */
478 	if (LIST_NEXT(session, session_list) == NULL)
479 		pipex_timer_start();
480 	session->state = PIPEX_STATE_OPENED;
481 
482 out:
483 	mtx_leave(&pipex_list_mtx);
484 
485 	return error;
486 }
487 
488 void
pipex_unlink_session_locked(struct pipex_session * session)489 pipex_unlink_session_locked(struct pipex_session *session)
490 {
491 	struct radix_node *rn;
492 
493 	MUTEX_ASSERT_LOCKED(&pipex_list_mtx);
494 
495 	session->ifindex = 0;
496 
497 	if (session->state == PIPEX_STATE_CLOSED)
498 		return;
499 	if ((session->flags & PIPEX_SFLAGS_PPPX) == 0 &&
500 	    !in_nullhost(session->ip_address.sin_addr)) {
501 		KASSERT(pipex_rd_head4 != NULL);
502 		rn = rn_delete(&session->ip_address, &session->ip_netmask,
503 		    pipex_rd_head4, (struct radix_node *)session);
504 		KASSERT(rn != NULL);
505 	}
506 
507 	LIST_REMOVE(session, id_chain);
508 #if defined(PIPEX_PPTP) || defined(PIPEX_L2TP)
509 	switch (session->protocol) {
510 	case PIPEX_PROTO_PPTP:
511 	case PIPEX_PROTO_L2TP:
512 		LIST_REMOVE(session, peer_addr_chain);
513 		break;
514 	}
515 #endif
516 	if (session->state == PIPEX_STATE_CLOSE_WAIT)
517 		LIST_REMOVE(session, state_list);
518 	LIST_REMOVE(session, session_list);
519 	session->state = PIPEX_STATE_CLOSED;
520 
521 	/* if final session is destroyed, stop timer */
522 	if (LIST_EMPTY(&pipex_session_list))
523 		pipex_timer_stop();
524 }
525 
526 void
pipex_unlink_session(struct pipex_session * session)527 pipex_unlink_session(struct pipex_session *session)
528 {
529 	mtx_enter(&pipex_list_mtx);
530 	pipex_unlink_session_locked(session);
531 	mtx_leave(&pipex_list_mtx);
532 }
533 
534 int
pipex_notify_close_session(struct pipex_session * session)535 pipex_notify_close_session(struct pipex_session *session)
536 {
537 	MUTEX_ASSERT_LOCKED(&pipex_list_mtx);
538 
539 	session->state = PIPEX_STATE_CLOSE_WAIT;
540 	session->idle_time = 0;
541 	LIST_INSERT_HEAD(&pipex_close_wait_list, session, state_list);
542 
543 	return (0);
544 }
545 
546 void
pipex_export_session_stats(struct pipex_session * session,struct pipex_statistics * stats)547 pipex_export_session_stats(struct pipex_session *session,
548     struct pipex_statistics *stats)
549 {
550 	uint64_t counters[pxc_ncounters];
551 
552 	memset(stats, 0, sizeof(*stats));
553 
554 	counters_read(session->stat_counters, counters, pxc_ncounters, NULL);
555 	stats->ipackets = counters[pxc_ipackets];
556 	stats->ierrors = counters[pxc_ierrors];
557 	stats->ibytes = counters[pxc_ibytes];
558 	stats->opackets = counters[pxc_opackets];
559 	stats->oerrors = counters[pxc_oerrors];
560 	stats->obytes = counters[pxc_obytes];
561 	stats->idle_time = session->idle_time;
562 }
563 
564 int
pipex_get_stat(struct pipex_session_stat_req * req,void * ownersc)565 pipex_get_stat(struct pipex_session_stat_req *req, void *ownersc)
566 {
567 	struct pipex_session *session;
568 	int error = 0;
569 
570 	session = pipex_lookup_by_session_id(req->psr_protocol,
571 	    req->psr_session_id);
572 	if (session == NULL)
573 		return (EINVAL);
574 
575 	if (session->ownersc == ownersc)
576 		pipex_export_session_stats(session, &req->psr_stat);
577 	else
578 		error = EINVAL;
579 
580 	pipex_rele_session(session);
581 
582 	return error;
583 }
584 
585 int
pipex_get_closed(struct pipex_session_list_req * req,void * ownersc)586 pipex_get_closed(struct pipex_session_list_req *req, void *ownersc)
587 {
588 	struct pipex_session *session, *session_tmp;
589 
590 	bzero(req, sizeof(*req));
591 
592 	mtx_enter(&pipex_list_mtx);
593 
594 	LIST_FOREACH_SAFE(session, &pipex_close_wait_list, state_list,
595 	    session_tmp) {
596 		if (session->flags & PIPEX_SFLAGS_ITERATOR)
597 			continue;
598 		if (session->ownersc != ownersc)
599 			continue;
600 		req->plr_ppp_id[req->plr_ppp_id_count++] = session->ppp_id;
601 		LIST_REMOVE(session, state_list);
602 		session->state = PIPEX_STATE_CLOSE_WAIT2;
603 		if (req->plr_ppp_id_count >= PIPEX_MAX_LISTREQ) {
604 			if (!LIST_EMPTY(&pipex_close_wait_list))
605 				req->plr_flags |= PIPEX_LISTREQ_MORE;
606 			break;
607 		}
608 	}
609 
610 	mtx_leave(&pipex_list_mtx);
611 
612 	return (0);
613 }
614 
615 struct pipex_session *
pipex_lookup_by_ip_address_locked(struct in_addr addr)616 pipex_lookup_by_ip_address_locked(struct in_addr addr)
617 {
618 	struct pipex_session *session;
619 	struct sockaddr_in pipex_in4, pipex_in4mask;
620 
621 	MUTEX_ASSERT_LOCKED(&pipex_list_mtx);
622 
623 	if (pipex_rd_head4 == NULL)
624 		return (NULL);
625 	bzero(&pipex_in4, sizeof(pipex_in4));
626 	pipex_in4.sin_addr = addr;
627 	pipex_in4.sin_family = AF_INET;
628 	pipex_in4.sin_len = sizeof(pipex_in4);
629 
630 	bzero(&pipex_in4mask, sizeof(pipex_in4mask));
631 	pipex_in4mask.sin_addr.s_addr = htonl(0xFFFFFFFFL);
632 	pipex_in4mask.sin_family = AF_INET;
633 	pipex_in4mask.sin_len = sizeof(pipex_in4mask);
634 
635 	session = (struct pipex_session *)rn_lookup(&pipex_in4, &pipex_in4mask,
636 	    pipex_rd_head4);
637 
638 #ifdef PIPEX_DEBUG
639 	if (session == NULL) {
640 		char buf[INET_ADDRSTRLEN];
641 
642 		PIPEX_DBG((NULL, LOG_DEBUG, "<%s> session not found (addr=%s)",
643 		    __func__, inet_ntop(AF_INET, &addr, buf, sizeof(buf))));
644 	}
645 #endif
646 
647 	return (session);
648 }
649 
650 struct pipex_session *
pipex_lookup_by_ip_address(struct in_addr addr)651 pipex_lookup_by_ip_address(struct in_addr addr)
652 {
653 	struct pipex_session *session;
654 
655 	mtx_enter(&pipex_list_mtx);
656 
657 	session = pipex_lookup_by_ip_address_locked(addr);
658 	if (session != NULL)
659 		refcnt_take(&session->pxs_refcnt);
660 
661 	mtx_leave(&pipex_list_mtx);
662 
663 	return (session);
664 }
665 
666 
667 struct pipex_session *
pipex_lookup_by_session_id_locked(int protocol,int session_id)668 pipex_lookup_by_session_id_locked(int protocol, int session_id)
669 {
670 	struct pipex_hash_head *list;
671 	struct pipex_session *session;
672 
673 	MUTEX_ASSERT_LOCKED(&pipex_list_mtx);
674 
675 	list = PIPEX_ID_HASHTABLE(session_id);
676 	LIST_FOREACH(session, list, id_chain) {
677 		if (session->protocol == protocol &&
678 		    session->session_id == session_id)
679 			break;
680 	}
681 
682 #ifdef PIPEX_DEBUG
683 	if (session == NULL)
684 		PIPEX_DBG((NULL, LOG_DEBUG,
685 		    "<%s> session not found (session_id=%d)", __func__,
686 		    session_id));
687 #endif
688 
689 	return (session);
690 }
691 
692 struct pipex_session *
pipex_lookup_by_session_id(int protocol,int session_id)693 pipex_lookup_by_session_id(int protocol, int session_id)
694 {
695 	struct pipex_session *session;
696 
697 	mtx_enter(&pipex_list_mtx);
698 
699 	session = pipex_lookup_by_session_id_locked(protocol, session_id);
700 	if (session != NULL)
701 		refcnt_take(&session->pxs_refcnt);
702 
703 	mtx_leave(&pipex_list_mtx);
704 
705 	return (session);
706 }
707 
708 /***********************************************************************
709  * Timer functions
710  ***********************************************************************/
711 void
pipex_timer_start(void)712 pipex_timer_start(void)
713 {
714 	timeout_set_flags(&pipex_timer_ch, pipex_timer, NULL,
715 	    KCLOCK_NONE, TIMEOUT_PROC | TIMEOUT_MPSAFE);
716 	timeout_add_sec(&pipex_timer_ch, pipex_prune);
717 }
718 
719 void
pipex_timer_stop(void)720 pipex_timer_stop(void)
721 {
722 	timeout_del(&pipex_timer_ch);
723 }
724 
725 void
pipex_timer(void * ignored_arg)726 pipex_timer(void *ignored_arg)
727 {
728 	struct pipex_session *session, *session_tmp;
729 
730 	mtx_enter(&pipex_list_mtx);
731 	/* walk through */
732 	LIST_FOREACH_SAFE(session, &pipex_session_list, session_list,
733 	    session_tmp) {
734 		if (session->flags & PIPEX_SFLAGS_ITERATOR)
735 			continue;
736 		switch (session->state) {
737 		case PIPEX_STATE_OPENED:
738 			if (session->timeout_sec == 0)
739 				continue;
740 
741 			session->idle_time++;
742 			if (session->idle_time < session->timeout_sec)
743 				continue;
744 
745 			pipex_notify_close_session(session);
746 			break;
747 
748 		case PIPEX_STATE_CLOSE_WAIT:
749 		case PIPEX_STATE_CLOSE_WAIT2:
750 			/* Waiting PIPEXDSESSION from userland */
751 			session->idle_time++;
752 			if (session->idle_time < PIPEX_CLOSE_TIMEOUT)
753 				continue;
754 			/* Release the sessions when timeout */
755 			pipex_unlink_session_locked(session);
756 			KASSERTMSG((session->flags & PIPEX_SFLAGS_PPPX) == 0,
757 			    "FIXME session must not be released when pppx");
758 			pipex_rele_session(session);
759 			break;
760 
761 		default:
762 			break;
763 		}
764 	}
765 
766 	if (LIST_FIRST(&pipex_session_list))
767 		timeout_add_sec(&pipex_timer_ch, pipex_prune);
768 
769 	mtx_leave(&pipex_list_mtx);
770 }
771 
772 /***********************************************************************
773  * Common network I/O functions.  (tunnel protocol independent)
774  ***********************************************************************/
775 
776 struct pipex_session *
pipex_iterator(struct pipex_session * session,struct pipex_session_iterator * iter,void * ownersc)777 pipex_iterator(struct pipex_session *session,
778     struct pipex_session_iterator *iter, void *ownersc)
779 {
780 	struct pipex_session *session_tmp;
781 
782 	mtx_enter(&pipex_list_mtx);
783 
784 	if (session)
785 		session_tmp = LIST_NEXT(session, session_list);
786 	else
787 		session_tmp = LIST_FIRST(&pipex_session_list);
788 
789 	while (session_tmp) {
790 		if (session_tmp->flags & PIPEX_SFLAGS_ITERATOR)
791 			goto next;
792 		if (session_tmp->ownersc != ownersc)
793 			goto next;
794 		break;
795 next:
796 		session_tmp = LIST_NEXT(session_tmp, session_list);
797 	}
798 
799 	if (session)
800 		LIST_REMOVE(iter, session_list);
801 
802 	if (session_tmp) {
803 		LIST_INSERT_AFTER(session_tmp,
804 		    (struct pipex_session *)&iter, session_list);
805 		refcnt_take(&session_tmp->pxs_refcnt);
806 	}
807 
808 	mtx_leave(&pipex_list_mtx);
809 
810 	if (session)
811 		pipex_rele_session(session);
812 
813 	return (session_tmp);
814 }
815 
816 void
pipex_ip_output(struct mbuf * m0,struct pipex_session * session)817 pipex_ip_output(struct mbuf *m0, struct pipex_session *session)
818 {
819 	int is_idle;
820 
821 	if ((session->flags & PIPEX_SFLAGS_MULTICAST) == 0) {
822 		/*
823 		 * Multicast packet is a idle packet and it's not TCP.
824 		 */
825 
826 		/* reset idle timer */
827 		if (session->timeout_sec != 0) {
828 			is_idle = 0;
829 			m0 = ip_is_idle_packet(m0, &is_idle);
830 			if (m0 == NULL)
831 				goto dropped;
832 			if (is_idle == 0) {
833 				mtx_enter(&pipex_list_mtx);
834 				/* update expire time */
835 				if (session->state == PIPEX_STATE_OPENED)
836 					session->idle_time = 0;
837 				mtx_leave(&pipex_list_mtx);
838 			}
839 		}
840 
841 		/* adjust tcpmss */
842 		if ((session->ppp_flags & PIPEX_PPP_ADJUST_TCPMSS) != 0) {
843 			m0 = adjust_tcp_mss(m0, session->peer_mru);
844 			if (m0 == NULL)
845 				goto dropped;
846 		}
847 
848 		pipex_ppp_output(m0, session, PPP_IP);
849 	} else {
850 		struct pipex_session_iterator iter = {
851 			.flags = PIPEX_SFLAGS_ITERATOR,
852 		};
853 
854 		struct pipex_session *session_tmp;
855 		struct mbuf *m;
856 
857 		m0->m_flags &= ~(M_BCAST|M_MCAST);
858 
859 		session_tmp = pipex_iterator(NULL, &iter, session->ownersc);
860 		while (session_tmp) {
861 			m = m_copym(m0, 0, M_COPYALL, M_NOWAIT);
862 			if (m != NULL)
863 				pipex_ppp_output(m, session_tmp, PPP_IP);
864 			else
865 				counters_inc(session_tmp->stat_counters,
866 				    pxc_oerrors);
867 
868 			session_tmp = pipex_iterator(session_tmp,
869 			    &iter, session->ownersc);
870 		}
871 
872 		m_freem(m0);
873 	}
874 
875 	return;
876 dropped:
877 	counters_inc(session->stat_counters, pxc_oerrors);
878 }
879 
880 void
pipex_ppp_output(struct mbuf * m0,struct pipex_session * session,int proto)881 pipex_ppp_output(struct mbuf *m0, struct pipex_session *session, int proto)
882 {
883 	u_char *cp, hdr[16];
884 
885 #ifdef PIPEX_MPPE
886 	if (pipex_session_is_mppe_enabled(session)) {
887 		if (proto == PPP_IP) {
888 			m0 = pipex_mppe_output(m0, session, PPP_IP);
889 			if (m0 == NULL)
890 				goto drop;
891 
892 			proto = PPP_COMP;
893 		}
894 	}
895 #endif /* PIPEX_MPPE */
896 	cp = hdr;
897 	if (session->protocol != PIPEX_PROTO_PPPOE) {
898 		/* PPPoE has not address and control field */
899 		PUTCHAR(PPP_ALLSTATIONS, cp);
900 		PUTCHAR(PPP_UI, cp);
901 	}
902 	PUTSHORT(proto, cp);
903 
904 	M_PREPEND(m0, cp - hdr, M_NOWAIT);
905 	if (m0 == NULL)
906 		goto drop;
907 	memcpy(mtod(m0, u_char *), hdr, cp - hdr);
908 
909 	switch (session->protocol) {
910 #ifdef	PIPEX_PPPOE
911 	case PIPEX_PROTO_PPPOE:
912 		pipex_pppoe_output(m0, session);
913 		break;
914 #endif
915 #ifdef PIPEX_PPTP
916 	case PIPEX_PROTO_PPTP:
917 		mtx_enter(&session->pxs_mtx);
918 		pipex_pptp_output(m0, session, 1, 1);
919 		mtx_leave(&session->pxs_mtx);
920 		break;
921 #endif
922 #ifdef	PIPEX_L2TP
923 	case PIPEX_PROTO_L2TP:
924 		pipex_l2tp_output(m0, session);
925 		break;
926 #endif
927 	default:
928 		goto drop;
929 	}
930 
931 	return;
932 drop:
933 	m_freem(m0);
934 	counters_inc(session->stat_counters, pxc_oerrors);
935 }
936 
937 void
pipex_ppp_input(struct mbuf * m0,struct pipex_session * session,int decrypted)938 pipex_ppp_input(struct mbuf *m0, struct pipex_session *session, int decrypted)
939 {
940 	int proto, hlen = 0;
941 	struct mbuf *n;
942 
943 #ifdef PIPEX_MPPE
944 again:
945 #endif
946 
947 	KASSERT(m0->m_pkthdr.len >= PIPEX_PPPMINLEN);
948 	proto = pipex_ppp_proto(m0, session, 0, &hlen);
949 #ifdef PIPEX_MPPE
950 	if (proto == PPP_COMP) {
951 		if (decrypted)
952 			goto drop;
953 
954 		/* checked this on ppp_common_input() already. */
955 		KASSERT(pipex_session_is_mppe_accepted(session));
956 
957 		m_adj(m0, hlen);
958 		m0 = pipex_mppe_input(m0, session);
959 		if (m0 == NULL)
960 			goto drop;
961 		decrypted = 1;
962 
963 		goto again;
964 	}
965 	if (proto == PPP_CCP) {
966 		if (decrypted)
967 			goto drop;
968 
969 #if NBPFILTER > 0
970 	    {
971 		struct ifnet *ifp;
972 
973 		if ((ifp = if_get(session->ifindex)) != NULL) {
974 			if (ifp->if_bpf && ifp->if_type == IFT_PPP)
975 				bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_IN);
976 		}
977 		if_put(ifp);
978 	    }
979 #endif
980 		m_adj(m0, hlen);
981 		pipex_ccp_input(m0, session);
982 		return;
983 	}
984 #endif
985 	m_adj(m0, hlen);
986 	if (!ALIGNED_POINTER(mtod(m0, caddr_t), uint32_t)) {
987 		n = m_dup_pkt(m0, 0, M_NOWAIT);
988 		if (n == NULL)
989 			goto drop;
990 		m_freem(m0);
991 		m0 = n;
992 	}
993 
994 	switch (proto) {
995 	case PPP_IP:
996 		if (!decrypted && pipex_session_is_mppe_required(session))
997 			/*
998 			 * if ip packet received when mppe
999 			 * is required, discard it.
1000 			 */
1001 			goto drop;
1002 		pipex_ip_input(m0, session);
1003 		return;
1004 #ifdef INET6
1005 	case PPP_IPV6:
1006 		if (!decrypted && pipex_session_is_mppe_required(session))
1007 			/*
1008 			 * if ip packet received when mppe
1009 			 * is required, discard it.
1010 			 */
1011 			goto drop;
1012 		pipex_ip6_input(m0, session);
1013 		return;
1014 #endif
1015 	default:
1016 		if (decrypted)
1017 			goto drop;
1018 		/* protocol must be checked on pipex_common_input() already */
1019 		KASSERT(0);
1020 		goto drop;
1021 	}
1022 
1023 	return;
1024 
1025 drop:
1026 	m_freem(m0);
1027 	counters_inc(session->stat_counters, pxc_ierrors);
1028 }
1029 
1030 void
pipex_ip_input(struct mbuf * m0,struct pipex_session * session)1031 pipex_ip_input(struct mbuf *m0, struct pipex_session *session)
1032 {
1033 	struct ifnet *ifp;
1034 	struct ip *ip;
1035 	int len;
1036 	int is_idle;
1037 
1038 	/* change recvif */
1039 	m0->m_pkthdr.ph_ifidx = session->ifindex;
1040 
1041 	if (ISSET(session->ppp_flags, PIPEX_PPP_INGRESS_FILTER)) {
1042 		PIPEX_PULLUP(m0, sizeof(struct ip));
1043 		if (m0 == NULL)
1044 			goto drop;
1045 		/* ingress filter */
1046 		ip = mtod(m0, struct ip *);
1047 		if ((ip->ip_src.s_addr & session->ip_netmask.sin_addr.s_addr) !=
1048 		    session->ip_address.sin_addr.s_addr) {
1049 			char src[INET_ADDRSTRLEN];
1050 
1051 			pipex_session_log(session, LOG_DEBUG,
1052 			    "ip packet discarded by ingress filter (src %s)",
1053 			    inet_ntop(AF_INET, &ip->ip_src, src, sizeof(src)));
1054 			goto drop;
1055 		}
1056 	}
1057 
1058 	/* idle timer */
1059 	if (session->timeout_sec != 0) {
1060 		is_idle = 0;
1061 		m0 = ip_is_idle_packet(m0, &is_idle);
1062 		if (m0 == NULL)
1063 			goto drop;
1064 		if (is_idle == 0) {
1065 			/* update expire time */
1066 			mtx_enter(&pipex_list_mtx);
1067 			if (session->state == PIPEX_STATE_OPENED)
1068 				session->idle_time = 0;
1069 			mtx_leave(&pipex_list_mtx);
1070 		}
1071 	}
1072 
1073 	/* adjust tcpmss */
1074 	if (session->ppp_flags & PIPEX_PPP_ADJUST_TCPMSS) {
1075 		m0 = adjust_tcp_mss(m0, session->peer_mru);
1076 		if (m0 == NULL)
1077 			goto drop;
1078 	}
1079 
1080 #if NPF > 0
1081 	pf_pkt_addr_changed(m0);
1082 #endif
1083 
1084 	len = m0->m_pkthdr.len;
1085 
1086 	if ((ifp = if_get(session->ifindex)) == NULL)
1087 		goto drop;
1088 
1089 #if NBPFILTER > 0
1090 	if (ifp->if_bpf)
1091 		bpf_mtap_af(ifp->if_bpf, AF_INET, m0, BPF_DIRECTION_IN);
1092 #endif
1093 
1094 	counters_pkt(ifp->if_counters, ifc_ipackets, ifc_ibytes, len);
1095 	counters_pkt(session->stat_counters, pxc_ipackets, pxc_ibytes, len);
1096 	ipv4_input(ifp, m0);
1097 
1098 	if_put(ifp);
1099 
1100 	return;
1101 drop:
1102 	m_freem(m0);
1103 	counters_inc(session->stat_counters, pxc_ierrors);
1104 }
1105 
1106 #ifdef INET6
1107 void
pipex_ip6_input(struct mbuf * m0,struct pipex_session * session)1108 pipex_ip6_input(struct mbuf *m0, struct pipex_session *session)
1109 {
1110 	struct ifnet *ifp;
1111 	int len;
1112 
1113 	/* change recvif */
1114 	m0->m_pkthdr.ph_ifidx = session->ifindex;
1115 
1116 	/*
1117 	 * XXX: what is reasonable ingress filter ???
1118 	 *      only one address is enough ??
1119 	 */
1120 
1121 	/* XXX: we must define idle packet for IPv6(ICMPv6). */
1122 
1123 	/*
1124 	 * XXX: tcpmss adjustment for IPv6 is required???
1125 	 *      We may use PMTUD in IPv6....
1126 	 */
1127 
1128 #if NPF > 0
1129 	pf_pkt_addr_changed(m0);
1130 #endif
1131 
1132 	len = m0->m_pkthdr.len;
1133 
1134 	if ((ifp = if_get(session->ifindex)) == NULL)
1135 		goto drop;
1136 
1137 #if NBPFILTER > 0
1138 	if (ifp->if_bpf)
1139 		bpf_mtap_af(ifp->if_bpf, AF_INET6, m0, BPF_DIRECTION_IN);
1140 #endif
1141 
1142 	counters_pkt(ifp->if_counters, ifc_ipackets, ifc_ibytes, len);
1143 	counters_pkt(session->stat_counters, pxc_ipackets, pxc_ibytes, len);
1144 	ipv6_input(ifp, m0);
1145 
1146 	if_put(ifp);
1147 
1148 	return;
1149 drop:
1150 	m_freem(m0);
1151 	counters_inc(session->stat_counters, pxc_ierrors);
1152 }
1153 #endif
1154 
1155 struct mbuf *
pipex_common_input(struct pipex_session * session,struct mbuf * m0,int hlen,int plen,int locked)1156 pipex_common_input(struct pipex_session *session, struct mbuf *m0, int hlen,
1157     int plen, int locked)
1158 {
1159 	int proto, ppphlen;
1160 	u_char code;
1161 
1162 	if ((m0->m_pkthdr.len < hlen + PIPEX_PPPMINLEN) ||
1163 	    (plen < PIPEX_PPPMINLEN)) {
1164 		if (locked)
1165 			mtx_leave(&session->pxs_mtx);
1166 		goto drop;
1167 	}
1168 
1169 	proto = pipex_ppp_proto(m0, session, hlen, &ppphlen);
1170 	switch (proto) {
1171 #ifdef PIPEX_MPPE
1172 	case PPP_CCP:
1173 		code = 0;
1174 		KASSERT(m0->m_pkthdr.len >= hlen + ppphlen + 1);
1175 		m_copydata(m0, hlen + ppphlen, 1, &code);
1176 		if (code != CCP_RESETREQ && code != CCP_RESETACK)
1177 			goto not_ours;
1178 		break;
1179 
1180 	case PPP_COMP:
1181 		if (pipex_session_is_mppe_accepted(session))
1182 			break;
1183 		goto not_ours;
1184 #endif
1185 	case PPP_IP:
1186 #ifdef INET6
1187 	case PPP_IPV6:
1188 #endif
1189 		break;
1190 	default:
1191 		goto not_ours;
1192 	}
1193 
1194 	if (locked)
1195 		mtx_leave(&session->pxs_mtx);
1196 
1197 	/* ok,  The packet is for PIPEX */
1198 	m_adj(m0, hlen);/* cut off the tunnel protocol header */
1199 
1200 	/* ensure the mbuf length equals the PPP frame length */
1201 	if (m0->m_pkthdr.len < plen)
1202 		goto drop;
1203 	if (m0->m_pkthdr.len > plen) {
1204 		if (m0->m_len == m0->m_pkthdr.len) {
1205 			m0->m_len = plen;
1206 			m0->m_pkthdr.len = plen;
1207 		} else
1208 			m_adj(m0, plen - m0->m_pkthdr.len);
1209 	}
1210 
1211 	pipex_ppp_input(m0, session, 0);
1212 
1213 	return (NULL);
1214 
1215 drop:
1216 	m_freem(m0);
1217 	counters_inc(session->stat_counters, pxc_ierrors);
1218 	return (NULL);
1219 
1220 not_ours:
1221 	return (m0);	/* Not to be handled by PIPEX */
1222 }
1223 
1224 /*
1225  * pipex_ppp_proto
1226  */
1227 int
pipex_ppp_proto(struct mbuf * m0,struct pipex_session * session,int off,int * hlenp)1228 pipex_ppp_proto(struct mbuf *m0, struct pipex_session *session, int off,
1229     int *hlenp)
1230 {
1231 	int proto;
1232 	u_char *cp, pktbuf[4];
1233 
1234 	KASSERT(m0->m_pkthdr.len > sizeof(pktbuf));
1235 	m_copydata(m0, off, sizeof(pktbuf), pktbuf);
1236 	cp = pktbuf;
1237 
1238 	if (pipex_session_has_acf(session)) {
1239 		if (cp[0] == PPP_ALLSTATIONS && cp[1] == PPP_UI)
1240 			cp += 2;
1241 #ifdef PIPEX_DEBUG
1242 		else if (!pipex_session_is_acfc_accepted(session))
1243 			PIPEX_DBG((session, LOG_DEBUG,
1244 			    "no acf but acfc is not accepted by the peer."));
1245 #endif
1246 	}
1247 	if ((*cp & 0x01) != 0) {
1248 		if (!pipex_session_is_pfc_accepted(session)) {
1249 			PIPEX_DBG((session, LOG_DEBUG, "Received a broken ppp "
1250 			    "frame.  No protocol field. %02x-%02x",
1251 			    cp[0], cp[1]));
1252 			return (-1);
1253 		}
1254 		GETCHAR(proto, cp);
1255 	} else
1256 		GETSHORT(proto, cp);
1257 
1258 	if (hlenp != NULL)
1259 		*hlenp = cp - pktbuf;
1260 
1261 	return (proto);
1262 }
1263 
1264 #ifdef PIPEX_PPPOE
1265 /***********************************************************************
1266  * PPPoE
1267  ***********************************************************************/
1268 static const u_char	pipex_pppoe_padding[ETHERMIN];
1269 /*
1270  * pipex_pppoe_lookup_session
1271  */
1272 struct pipex_session *
pipex_pppoe_lookup_session(struct mbuf * m0)1273 pipex_pppoe_lookup_session(struct mbuf *m0)
1274 {
1275 	struct pipex_session *session;
1276 	struct pipex_pppoe_header pppoe;
1277 	struct ether_header eh;
1278 
1279 	/* short packet */
1280 	if (m0->m_pkthdr.len < (sizeof(struct ether_header) + sizeof(pppoe)))
1281 		return (NULL);
1282 
1283 	m_copydata(m0, sizeof(struct ether_header),
1284 	    sizeof(struct pipex_pppoe_header), &pppoe);
1285 	pppoe.session_id = ntohs(pppoe.session_id);
1286 	session = pipex_lookup_by_session_id(PIPEX_PROTO_PPPOE,
1287 	    pppoe.session_id);
1288 #ifdef PIPEX_DEBUG
1289 	if (session == NULL)
1290 		PIPEX_DBG((NULL, LOG_DEBUG, "<%s> session not found (id=%d)",
1291 		    __func__, pppoe.session_id));
1292 #endif
1293 	m_copydata(m0, 0, sizeof(struct ether_header), &eh);
1294 	if (session && (session->proto.pppoe.over_ifidx !=
1295 	    m0->m_pkthdr.ph_ifidx || memcmp(
1296 	    ((struct ether_header *)session->peer.sa.sa_data)->ether_dhost,
1297 	    eh.ether_shost, ETHER_ADDR_LEN) != 0)) {
1298 		PIPEX_DBG((NULL, LOG_DEBUG,
1299 		    "<%s> received packet from wrong host (id=%d)", __func__,
1300 		    pppoe.session_id));
1301 		pipex_rele_session(session);
1302 		session = NULL;
1303 	}
1304 
1305 	return (session);
1306 }
1307 
1308 struct mbuf *
pipex_pppoe_input(struct mbuf * m0,struct pipex_session * session)1309 pipex_pppoe_input(struct mbuf *m0, struct pipex_session *session)
1310 {
1311 	int hlen;
1312 	struct pipex_pppoe_header pppoe;
1313 
1314 	/* already checked at pipex_pppoe_lookup_session */
1315 	KASSERT(m0->m_pkthdr.len >= (sizeof(struct ether_header) +
1316 	    sizeof(pppoe)));
1317 
1318 	m_copydata(m0, sizeof(struct ether_header),
1319 	    sizeof(struct pipex_pppoe_header), &pppoe);
1320 
1321 	hlen = sizeof(struct ether_header) + sizeof(struct pipex_pppoe_header);
1322 	m0 = pipex_common_input(session, m0, hlen, ntohs(pppoe.length), 0);
1323 	if (m0 == NULL)
1324 		return (NULL);
1325 	m_freem(m0);
1326 	counters_inc(session->stat_counters, pxc_ierrors);
1327 	return (NULL);
1328 }
1329 
1330 /*
1331  * pipex_ppope_output
1332  */
1333 void
pipex_pppoe_output(struct mbuf * m0,struct pipex_session * session)1334 pipex_pppoe_output(struct mbuf *m0, struct pipex_session *session)
1335 {
1336 	struct pipex_pppoe_header *pppoe;
1337 	int len, padlen;
1338 
1339 	/* save length for pppoe header */
1340 	len = m0->m_pkthdr.len;
1341 
1342 	/* prepend protocol header */
1343 	M_PREPEND(m0, sizeof(struct pipex_pppoe_header), M_NOWAIT);
1344 	if (m0 == NULL) {
1345 		PIPEX_DBG((NULL, LOG_ERR,
1346 		    "<%s> cannot prepend header.", __func__));
1347 		counters_inc(session->stat_counters, pxc_oerrors);
1348 		return;
1349 	}
1350 	padlen = ETHERMIN - m0->m_pkthdr.len;
1351 	if (padlen > 0)
1352 		m_copyback(m0, m0->m_pkthdr.len, padlen, pipex_pppoe_padding,
1353 		    M_NOWAIT);
1354 
1355 	/* setup pppoe header information */
1356 	pppoe = mtod(m0, struct pipex_pppoe_header *);
1357 	pppoe->vertype = PIPEX_PPPOE_VERTYPE;
1358 	pppoe->code = PIPEX_PPPOE_CODE_SESSION;
1359 	pppoe->session_id = htons(session->session_id);
1360 	pppoe->length = htons(len);
1361 
1362 	m0->m_pkthdr.ph_ifidx = session->proto.pppoe.over_ifidx;
1363 	refcnt_take(&session->pxs_refcnt);
1364 	m0->m_pkthdr.ph_cookie = session;
1365 	m0->m_flags &= ~(M_BCAST|M_MCAST);
1366 
1367 	if (mq_enqueue(&pipexoutq, m0) != 0) {
1368 		counters_inc(session->stat_counters, pxc_oerrors);
1369 		pipex_rele_session(session);
1370 	} else
1371 		schednetisr(NETISR_PIPEX);
1372 }
1373 #endif /* PIPEX_PPPOE */
1374 
1375 #ifdef PIPEX_PPTP
1376 /***********************************************************************
1377  * PPTP
1378  ***********************************************************************/
1379 void
pipex_pptp_output(struct mbuf * m0,struct pipex_session * session,int has_seq,int has_ack)1380 pipex_pptp_output(struct mbuf *m0, struct pipex_session *session,
1381     int has_seq, int has_ack)
1382 {
1383 	int len, reqlen;
1384 	struct pipex_gre_header *gre = NULL;
1385 	struct ip *ip;
1386 	u_char *cp;
1387 
1388 	MUTEX_ASSERT_LOCKED(&session->pxs_mtx);
1389 
1390 	reqlen = PIPEX_IPGRE_HDRLEN + (has_seq + has_ack) * 4;
1391 
1392 	len = 0;
1393 	if (m0 != NULL) {
1394 		/* save length for gre header */
1395 		len = m0->m_pkthdr.len;
1396 		/* prepend protocol header */
1397 		M_PREPEND(m0, reqlen, M_NOWAIT);
1398 		if (m0 == NULL)
1399 			goto drop;
1400 	} else {
1401 		MGETHDR(m0, M_DONTWAIT, MT_DATA);
1402 		if (m0 && reqlen > MHLEN) {
1403 			MCLGET(m0, M_DONTWAIT);
1404 			if ((m0->m_flags & M_EXT) == 0) {
1405 				m_freem(m0);
1406 				m0 = NULL;
1407 			}
1408 		}
1409 		if (m0 == NULL)
1410 			goto drop;
1411 		m0->m_pkthdr.len = m0->m_len = reqlen;
1412 	}
1413 
1414 	/* setup ip header information */
1415 	ip = mtod(m0, struct ip *);
1416 
1417 	ip->ip_len = htons(m0->m_pkthdr.len);
1418 	ip->ip_off = 0;
1419 	ip->ip_ttl = MAXTTL;
1420 	ip->ip_p = IPPROTO_GRE;
1421 	ip->ip_tos = 0;
1422 
1423 	ip->ip_src = session->local.sin4.sin_addr;
1424 	ip->ip_dst = session->peer.sin4.sin_addr;
1425 #if NPF > 0
1426 	pf_pkt_addr_changed(m0);
1427 #endif
1428 
1429 	/* setup gre(ver1) header information */
1430 	gre = PIPEX_SEEK_NEXTHDR(ip, sizeof(struct ip),
1431 	    struct pipex_gre_header *);
1432 	gre->type = htons(PIPEX_GRE_PROTO_PPP);
1433 	gre->call_id = htons(session->peer_session_id);
1434 	gre->flags = PIPEX_GRE_KFLAG | PIPEX_GRE_VER;	/* do htons later */
1435 	gre->len = htons(len);
1436 
1437 	cp = PIPEX_SEEK_NEXTHDR(gre, sizeof(struct pipex_gre_header),u_char *);
1438 	if (has_seq) {
1439 		gre->flags |= PIPEX_GRE_SFLAG;
1440 		PUTLONG(session->proto.pptp.snd_nxt, cp);
1441 		session->proto.pptp.snd_nxt++;
1442 		session->proto.pptp.snd_gap++;
1443 	}
1444 	if (has_ack) {
1445 		gre->flags |= PIPEX_GRE_AFLAG;
1446 		session->proto.pptp.rcv_acked = session->proto.pptp.rcv_nxt - 1;
1447 		PUTLONG(session->proto.pptp.rcv_acked, cp);
1448 	}
1449 	gre->flags = htons(gre->flags);
1450 
1451 	m0->m_pkthdr.ph_ifidx = session->ifindex;
1452 	ip_send(m0);
1453 	if (len > 0) {	/* network layer only */
1454 		/* countup statistics */
1455 		counters_pkt(session->stat_counters, pxc_opackets,
1456 		    pxc_obytes, len);
1457 	}
1458 
1459 	return;
1460 drop:
1461 	counters_inc(session->stat_counters, pxc_oerrors);
1462 }
1463 
1464 struct pipex_session *
pipex_pptp_lookup_session(struct mbuf * m0)1465 pipex_pptp_lookup_session(struct mbuf *m0)
1466 {
1467 	struct pipex_session *session;
1468 	struct pipex_gre_header gre;
1469 	struct ip ip;
1470 	uint16_t flags;
1471 	uint16_t id;
1472 	int hlen;
1473 
1474 	if (m0->m_pkthdr.len < PIPEX_IPGRE_HDRLEN) {
1475 		PIPEX_DBG((NULL, LOG_DEBUG,
1476 		    "<%s> packet length is too short", __func__));
1477 		goto not_ours;
1478 	}
1479 
1480 	/* get ip header info */
1481 	m_copydata(m0, 0, sizeof(struct ip), &ip);
1482 	hlen = ip.ip_hl << 2;
1483 
1484 	/*
1485 	 * m0 has already passed ip_input(), so there is
1486 	 * no necessity for ip packet inspection.
1487 	 */
1488 
1489 	/* get gre flags */
1490 	m_copydata(m0, hlen, sizeof(gre), &gre);
1491 	flags = ntohs(gre.flags);
1492 
1493 	/* gre version must be '1' */
1494 	if ((flags & PIPEX_GRE_VERMASK) != PIPEX_GRE_VER) {
1495 		PIPEX_DBG((NULL, LOG_DEBUG,
1496 		    "<%s> gre header wrong version.", __func__));
1497 		goto not_ours;
1498 	}
1499 
1500 	/* gre keys must be present */
1501 	if ((flags & PIPEX_GRE_KFLAG) == 0) {
1502 		PIPEX_DBG((NULL, LOG_DEBUG,
1503 		    "<%s> gre header has no keys.", __func__));
1504 		goto not_ours;
1505 	}
1506 
1507 	/* flag check */
1508 	if ((flags & PIPEX_GRE_UNUSEDFLAGS) != 0) {
1509 		PIPEX_DBG((NULL, LOG_DEBUG,
1510 		    "<%s> gre header has unused flags at pptp.", __func__));
1511 		goto not_ours;
1512 	}
1513 
1514 	/* lookup pipex session table */
1515 	id = ntohs(gre.call_id);
1516 	session = pipex_lookup_by_session_id(PIPEX_PROTO_PPTP, id);
1517 	if (session == NULL) {
1518 		PIPEX_DBG((NULL, LOG_DEBUG,
1519 		    "<%s> session not found (id=%d)", __func__, id));
1520 		goto not_ours;
1521 	}
1522 
1523 	if (!(session->peer.sa.sa_family == AF_INET &&
1524 	    session->peer.sin4.sin_addr.s_addr == ip.ip_src.s_addr)) {
1525 		PIPEX_DBG((NULL, LOG_DEBUG,
1526 		    "<%s> the source address of the session is not matched",
1527 		    __func__));
1528 		pipex_rele_session(session);
1529 		session = NULL;
1530 	}
1531 
1532 	return (session);
1533 
1534 not_ours:
1535 	return (NULL);
1536 }
1537 
1538 struct mbuf *
pipex_pptp_input(struct mbuf * m0,struct pipex_session * session)1539 pipex_pptp_input(struct mbuf *m0, struct pipex_session *session)
1540 {
1541 	int hlen, has_seq, has_ack, nseq;
1542 	const char *reason = "";
1543 	u_char *cp, *seqp = NULL, *ackp = NULL;
1544 	uint32_t flags, seq = 0, ack = 0;
1545 	struct ip *ip;
1546 	struct pipex_gre_header *gre;
1547 	struct pipex_pptp_session *pptp_session;
1548 	int rewind = 0;
1549 
1550 	KASSERT(m0->m_pkthdr.len >= PIPEX_IPGRE_HDRLEN);
1551 	pptp_session = &session->proto.pptp;
1552 
1553 	/* get ip header */
1554 	ip = mtod(m0, struct ip *);
1555 	hlen = ip->ip_hl << 2;
1556 
1557 	/* seek gre header */
1558 	gre = PIPEX_SEEK_NEXTHDR(ip, hlen, struct pipex_gre_header *);
1559 	flags = ntohs(gre->flags);
1560 
1561 	/* pullup for seek sequences in header */
1562 	has_seq = (flags & PIPEX_GRE_SFLAG) ? 1 : 0;
1563 	has_ack = (flags & PIPEX_GRE_AFLAG) ? 1 : 0;
1564 	hlen = PIPEX_IPGRE_HDRLEN + 4 * (has_seq + has_ack);
1565 	if (m0->m_len < hlen) {
1566 		m0 = m_pullup(m0, hlen);
1567 		if (m0 == NULL) {
1568 			PIPEX_DBG((session, LOG_DEBUG, "pullup failed."));
1569 			goto drop;
1570 		}
1571 	}
1572 
1573 	/* check sequence */
1574 	cp = PIPEX_SEEK_NEXTHDR(gre, sizeof(struct pipex_gre_header),u_char *);
1575 	if (has_seq) {
1576 		seqp = cp;
1577 		GETLONG(seq, cp);
1578 	}
1579 
1580 	mtx_enter(&session->pxs_mtx);
1581 
1582 	if (has_ack) {
1583 		ackp = cp;
1584 		GETLONG(ack, cp);
1585 		if (ack + 1 == pptp_session->snd_una) {
1586 			/* ack has not changed before */
1587 		} else if (SEQ32_LT(ack, pptp_session->snd_una)) {
1588 			/* OoO ack packets should not be dropped. */
1589 			rewind = 1;
1590 		} else if (SEQ32_GT(ack, pptp_session->snd_nxt)) {
1591 			reason = "ack for unknown sequence";
1592 			goto out_seq;
1593 		} else
1594 			pptp_session->snd_una = ack + 1;
1595 	}
1596 	if (!has_seq) {
1597 		/* ack only packet */
1598 		goto not_ours;
1599 	}
1600 	if (SEQ32_LT(seq, pptp_session->rcv_nxt)) {
1601 		rewind = 1;
1602 		if (SEQ32_LT(seq,
1603 		    pptp_session->rcv_nxt - PIPEX_REWIND_LIMIT)) {
1604 			reason = "out of sequence";
1605 			goto out_seq;
1606 		}
1607 	} else if (SEQ32_GE(seq, pptp_session->rcv_nxt +
1608 	    pptp_session->maxwinsz)) {
1609 		pipex_session_log(session, LOG_DEBUG,
1610 		    "received packet caused window overflow. seq=%u(%u-%u)"
1611 		    "may lost %d packets.", seq, pptp_session->rcv_nxt,
1612 		    pptp_session->rcv_nxt + pptp_session->maxwinsz,
1613 		    (int)SEQ32_SUB(seq, pptp_session->rcv_nxt));
1614 	}
1615 
1616 	seq++;
1617 	nseq = SEQ32_SUB(seq, pptp_session->rcv_nxt);
1618 	if (!rewind) {
1619 		pptp_session->rcv_nxt = seq;
1620 		if (SEQ32_SUB(seq, pptp_session->rcv_acked) >
1621 		    roundup(pptp_session->winsz, 2) / 2) /* Send ack only packet. */
1622 			pipex_pptp_output(NULL, session, 0, 1);
1623 	}
1624 
1625 	/*
1626 	 * The following pipex_common_input() will release `pxs_mtx'
1627 	 * deep within if the packet will be consumed. In the error
1628 	 * path lock will be held all the time. So increment `rcv_gap'
1629 	 * here, and on the error path back it out, no atomicity will
1630 	 * be lost in all cases.
1631 	 */
1632 	if (!rewind)
1633 		session->proto.pptp.rcv_gap += nseq;
1634 	m0 = pipex_common_input(session, m0, hlen, ntohs(gre->len), 1);
1635 	if (m0 == NULL) {
1636 		/*
1637 		 * pipex_common_input() releases lock if the
1638 		 * packet was consumed.
1639 		 */
1640 		return (NULL);
1641 	}
1642 
1643 	if (rewind)
1644 		goto out_seq;
1645 	else {
1646 		/* The packet is not ours, back out `rcv_gap'. */
1647 		session->proto.pptp.rcv_gap -= nseq;
1648 	}
1649 
1650 not_ours:
1651 	seq--;	/* revert original seq value */
1652 
1653 	/*
1654 	 * overwrite sequence numbers to adjust a gap between pipex and
1655 	 * userland.
1656 	 */
1657 	if (seqp != NULL) {
1658 		seq -= pptp_session->rcv_gap;
1659 		PUTLONG(seq, seqp);
1660 	}
1661 	if (ackp != NULL) {
1662 		if (pptp_session->snd_nxt == pptp_session->snd_una) {
1663 			ack -= session->proto.pptp.snd_gap;
1664 			pptp_session->ul_snd_una = ack;
1665 		} else {
1666 			/*
1667 			 * There are sending packets they are not acked.
1668 			 * In this situation, (ack - snd_gap) may points
1669 			 * before sending window of userland.  So we don't
1670 			 * update the ack number.
1671 			 */
1672 			ack = pptp_session->ul_snd_una;
1673 		}
1674 		PUTLONG(ack, ackp);
1675 	}
1676 
1677 	mtx_leave(&session->pxs_mtx);
1678 
1679 	return (m0);
1680 out_seq:
1681 	pipex_session_log(session, LOG_DEBUG,
1682 	    "Received bad data packet: %s: seq=%u(%u-%u) ack=%u(%u-%u)",
1683 	    reason, seq, pptp_session->rcv_nxt,
1684 	    pptp_session->rcv_nxt + pptp_session->maxwinsz,
1685 	    ack, pptp_session->snd_una,
1686 	    pptp_session->snd_nxt);
1687 	mtx_leave(&session->pxs_mtx);
1688 
1689 	/* FALLTHROUGH */
1690 drop:
1691 	m_freem(m0);
1692 	counters_inc(session->stat_counters, pxc_ierrors);
1693 
1694 	return (NULL);
1695 }
1696 
1697 struct pipex_session *
pipex_pptp_userland_lookup_session_ipv4(struct mbuf * m0,struct in_addr dst)1698 pipex_pptp_userland_lookup_session_ipv4(struct mbuf *m0, struct in_addr dst)
1699 {
1700 	struct sockaddr_in sin;
1701 
1702 	memset(&sin, 0, sizeof(sin));
1703 	sin.sin_len = sizeof(sin);
1704 	sin.sin_family = AF_INET;
1705 	sin.sin_addr = dst;
1706 
1707 	return pipex_pptp_userland_lookup_session(m0, sintosa(&sin));
1708 }
1709 
1710 #ifdef INET6
1711 struct pipex_session *
pipex_pptp_userland_lookup_session_ipv6(struct mbuf * m0,struct in6_addr dst)1712 pipex_pptp_userland_lookup_session_ipv6(struct mbuf *m0, struct in6_addr dst)
1713 {
1714 	struct sockaddr_in6 sin6;
1715 
1716 	memset(&sin6, 0, sizeof(sin6));
1717 	sin6.sin6_len = sizeof(sin6);
1718 	sin6.sin6_family = AF_INET6;
1719 	in6_recoverscope(&sin6, &dst);
1720 
1721 	return pipex_pptp_userland_lookup_session(m0, sin6tosa(&sin6));
1722 }
1723 #endif
1724 
1725 struct pipex_session *
pipex_pptp_userland_lookup_session(struct mbuf * m0,struct sockaddr * sa)1726 pipex_pptp_userland_lookup_session(struct mbuf *m0, struct sockaddr *sa)
1727 {
1728 	struct pipex_gre_header gre;
1729 	struct pipex_hash_head *list;
1730 	struct pipex_session *session;
1731 	uint16_t id, flags;
1732 
1733 	/* pullup */
1734 	if (m0->m_pkthdr.len < sizeof(gre)) {
1735 		PIPEX_DBG((NULL, LOG_DEBUG,
1736 		    "<%s> packet length is too short", __func__));
1737 		return (NULL);
1738 	}
1739 
1740 	/* get flags */
1741 	m_copydata(m0, 0, sizeof(struct pipex_gre_header), &gre);
1742 	flags = ntohs(gre.flags);
1743 
1744 	/* gre version must be '1' */
1745 	if ((flags & PIPEX_GRE_VERMASK) != PIPEX_GRE_VER) {
1746 		PIPEX_DBG((NULL, LOG_DEBUG,
1747 		    "<%s> gre header wrong version.", __func__));
1748 		return (NULL);
1749 	}
1750 
1751 	/* gre keys must be present */
1752 	if ((flags & PIPEX_GRE_KFLAG) == 0) {
1753 		PIPEX_DBG((NULL, LOG_DEBUG,
1754 		    "<%s> gre header has no keys.", __func__));
1755 		return (NULL);
1756 	}
1757 
1758 	/* lookup pipex session table */
1759 	id = ntohs(gre.call_id);
1760 
1761 	mtx_enter(&pipex_list_mtx);
1762 
1763 	list = PIPEX_PEER_ADDR_HASHTABLE(pipex_sockaddr_hash_key(sa));
1764 	LIST_FOREACH(session, list, peer_addr_chain) {
1765 		if (pipex_sockaddr_compar_addr(&session->peer.sa, sa) != 0)
1766 			continue;
1767 		if (session->peer_session_id == id)
1768 			break;
1769 	}
1770 
1771 	if (session != NULL)
1772 		refcnt_take(&session->pxs_refcnt);
1773 
1774 	mtx_leave(&pipex_list_mtx);
1775 
1776 #ifdef PIPEX_DEBUG
1777 	if (session == NULL) {
1778 		PIPEX_DBG((NULL, LOG_DEBUG,
1779 		    "<%s> session not found (,call_id=%d)",
1780 		    __func__, (int)gre.call_id));
1781 	}
1782 #endif
1783 	return (session);
1784 }
1785 
1786 /*
1787  * pipex_pptp_userland_output
1788  */
1789 struct mbuf *
pipex_pptp_userland_output(struct mbuf * m0,struct pipex_session * session)1790 pipex_pptp_userland_output(struct mbuf *m0, struct pipex_session *session)
1791 {
1792 	int len;
1793 	struct pipex_gre_header *gre, gre0;
1794 	uint16_t flags;
1795 	u_char *cp, *cp0;
1796 	uint32_t val32;
1797 
1798 	len = sizeof(struct pipex_gre_header);
1799 	m_copydata(m0, 0, len, &gre0);
1800 	gre = &gre0;
1801 	flags = ntohs(gre->flags);
1802 	if ((flags & PIPEX_GRE_SFLAG) != 0)
1803 		len += 4;
1804 	if ((flags & PIPEX_GRE_AFLAG) != 0)
1805 		len += 4;
1806 
1807 	/* check length */
1808 	PIPEX_PULLUP(m0, len);
1809 	if (m0 == NULL) {
1810 		PIPEX_DBG((session, LOG_DEBUG, "gre header is too short."));
1811 		return (NULL);
1812 	}
1813 
1814 	gre = mtod(m0, struct pipex_gre_header *);
1815 	cp = PIPEX_SEEK_NEXTHDR(gre, sizeof(struct pipex_gre_header), u_char *);
1816 
1817 	mtx_enter(&session->pxs_mtx);
1818 
1819 	/*
1820 	 * overwrite sequence numbers to adjust a gap between pipex and
1821 	 * userland.
1822 	 */
1823 	if ((flags & PIPEX_GRE_SFLAG) != 0) {
1824 		cp0 = cp;
1825 		GETLONG(val32, cp);
1826 		val32 += session->proto.pptp.snd_gap;
1827 		PUTLONG(val32, cp0);
1828 		session->proto.pptp.snd_nxt++;
1829 	}
1830 	if ((flags & PIPEX_GRE_AFLAG) != 0) {
1831 		cp0 = cp;
1832 		GETLONG(val32, cp);
1833 		val32 += session->proto.pptp.rcv_gap;
1834 		PUTLONG(val32, cp0);
1835 		if (SEQ32_GT(val32, session->proto.pptp.rcv_acked))
1836 			session->proto.pptp.rcv_acked = val32;
1837 	}
1838 
1839 	mtx_leave(&session->pxs_mtx);
1840 
1841 	return (m0);
1842 }
1843 #endif /* PIPEX_PPTP */
1844 
1845 #ifdef PIPEX_L2TP
1846 /***********************************************************************
1847  * L2TP support
1848  ***********************************************************************/
1849 void
pipex_l2tp_output(struct mbuf * m0,struct pipex_session * session)1850 pipex_l2tp_output(struct mbuf *m0, struct pipex_session *session)
1851 {
1852 	int hlen, plen, datalen;
1853 	struct pipex_l2tp_header *l2tp = NULL;
1854 	struct pipex_l2tp_seq_header *seq = NULL;
1855 	struct udphdr *udp;
1856 	struct ip *ip;
1857 #ifdef INET6
1858 	struct ip6_hdr *ip6;
1859 #endif
1860 	struct m_tag *mtag;
1861 
1862 	hlen = sizeof(struct pipex_l2tp_header) +
1863 	    ((pipex_session_is_l2tp_data_sequencing_on(session))
1864 		    ? sizeof(struct pipex_l2tp_seq_header) : 0) +
1865 	    sizeof(struct udphdr) +
1866 #ifdef INET6
1867 	    ((session->peer.sin6.sin6_family == AF_INET6)
1868 		    ? sizeof(struct ip6_hdr) : sizeof(struct ip));
1869 #else
1870 	    sizeof(struct ip);
1871 #endif
1872 
1873 	datalen = 0;
1874 	if (m0 != NULL) {
1875 		datalen = m0->m_pkthdr.len;
1876 		M_PREPEND(m0, hlen, M_NOWAIT);
1877 		if (m0 == NULL)
1878 			goto drop;
1879 	} else {
1880 		MGETHDR(m0, M_DONTWAIT, MT_DATA);
1881 		if (m0 == NULL)
1882 			goto drop;
1883 		KASSERT(hlen <= MHLEN);
1884 		m0->m_pkthdr.len = m0->m_len = hlen;
1885 	}
1886 
1887 #ifdef INET6
1888 	hlen = (session->peer.sin6.sin6_family == AF_INET6)
1889 	    ? sizeof(struct ip6_hdr) : sizeof(struct ip);
1890 #else
1891 	hlen = sizeof(struct ip);
1892 #endif
1893 	plen = datalen + sizeof(struct pipex_l2tp_header) +
1894 	    ((pipex_session_is_l2tp_data_sequencing_on(session))
1895 		    ? sizeof(struct pipex_l2tp_seq_header) : 0);
1896 
1897 	l2tp = (struct pipex_l2tp_header *)
1898 	    (mtod(m0, caddr_t) + hlen + sizeof(struct udphdr));
1899 	l2tp->flagsver = PIPEX_L2TP_VER | PIPEX_L2TP_FLAG_LENGTH;
1900 	l2tp->length = htons(plen);
1901 	l2tp->tunnel_id = htons(session->proto.l2tp.peer_tunnel_id);
1902 	l2tp->session_id = htons(session->peer_session_id);
1903 	if (pipex_session_is_l2tp_data_sequencing_on(session)) {
1904 		seq = (struct pipex_l2tp_seq_header *)(l2tp + 1);
1905 		l2tp->flagsver |= PIPEX_L2TP_FLAG_SEQUENCE;
1906 
1907 		mtx_enter(&session->pxs_mtx);
1908 		seq->ns = htons(session->proto.l2tp.ns_nxt);
1909 		session->proto.l2tp.ns_nxt++;
1910 		session->proto.l2tp.ns_gap++;
1911 		session->proto.l2tp.nr_acked = session->proto.l2tp.nr_nxt - 1;
1912 		seq->nr = htons(session->proto.l2tp.nr_acked);
1913 		mtx_leave(&session->pxs_mtx);
1914 	}
1915 	l2tp->flagsver = htons(l2tp->flagsver);
1916 
1917 	plen += sizeof(struct udphdr);
1918 	udp = (struct udphdr *)(mtod(m0, caddr_t) + hlen);
1919 	udp->uh_sport = session->local.sin6.sin6_port;
1920 	udp->uh_dport = session->peer.sin6.sin6_port;
1921 	udp->uh_ulen = htons(plen);
1922 	udp->uh_sum = 0;
1923 
1924 	m0->m_pkthdr.csum_flags |= M_UDP_CSUM_OUT;
1925 	m0->m_pkthdr.ph_ifidx = session->ifindex;
1926 #if NPF > 0
1927 	pf_pkt_addr_changed(m0);
1928 #endif
1929 	switch (session->peer.sin6.sin6_family) {
1930 	case AF_INET:
1931 		ip = mtod(m0, struct ip *);
1932 		ip->ip_p = IPPROTO_UDP;
1933 		ip->ip_src = session->local.sin4.sin_addr;
1934 		ip->ip_dst = session->peer.sin4.sin_addr;
1935 		ip->ip_len = htons(hlen + plen);
1936 		ip->ip_ttl = MAXTTL;
1937 		ip->ip_tos = 0;
1938 		ip->ip_off = 0;
1939 
1940 		mtx_enter(&session->pxs_mtx);
1941 		if (session->proto.l2tp.ipsecflowinfo > 0) {
1942 			if ((mtag = m_tag_get(PACKET_TAG_IPSEC_FLOWINFO,
1943 			    sizeof(u_int32_t), M_NOWAIT)) == NULL) {
1944 				mtx_leave(&session->pxs_mtx);
1945 				goto drop;
1946 			}
1947 
1948 			*(u_int32_t *)(mtag + 1) =
1949 			    session->proto.l2tp.ipsecflowinfo;
1950 			m_tag_prepend(m0, mtag);
1951 		}
1952 		mtx_leave(&session->pxs_mtx);
1953 
1954 		ip_send(m0);
1955 		break;
1956 #ifdef INET6
1957 	case AF_INET6:
1958 		ip6 = mtod(m0, struct ip6_hdr *);
1959 
1960 		ip6->ip6_flow = 0;
1961 		ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
1962 		ip6->ip6_vfc |= IPV6_VERSION;
1963 		ip6->ip6_nxt = IPPROTO_UDP;
1964 		ip6->ip6_src = session->local.sin6.sin6_addr;
1965 		in6_embedscope(&ip6->ip6_dst, &session->peer.sin6, NULL, NULL);
1966 		/* ip6->ip6_plen will be filled in ip6_output. */
1967 
1968 		ip6_send(m0);
1969 		break;
1970 #endif
1971 	}
1972 	udpstat_inc(udps_opackets);
1973 
1974 	if (datalen > 0) {	/* network layer only */
1975 		/* countup statistics */
1976 		counters_pkt(session->stat_counters, pxc_opackets,
1977 		    pxc_obytes, datalen);
1978 	}
1979 
1980 	return;
1981 drop:
1982 	m_freem(m0);
1983 	counters_inc(session->stat_counters, pxc_oerrors);
1984 }
1985 
1986 struct pipex_session *
pipex_l2tp_lookup_session(struct mbuf * m0,int off,struct sockaddr * sasrc)1987 pipex_l2tp_lookup_session(struct mbuf *m0, int off, struct sockaddr *sasrc)
1988 {
1989 	struct pipex_session *session;
1990 	uint16_t flags, session_id, ver;
1991 	u_char *cp, buf[PIPEX_L2TP_MINLEN];
1992 	int srcmatch = 0;
1993 
1994 	if (m0->m_pkthdr.len < off + PIPEX_L2TP_MINLEN) {
1995 		PIPEX_DBG((NULL, LOG_DEBUG,
1996 		    "<%s> packet length is too short", __func__));
1997 		goto not_ours;
1998 	}
1999 
2000 	/* get first 16bits of L2TP */
2001 	m_copydata(m0, off, sizeof(buf), buf);
2002 	cp = buf;
2003 	GETSHORT(flags, cp);
2004 	ver = flags & PIPEX_L2TP_VER_MASK;
2005 
2006 	/* l2tp version must be '2' */
2007 	if (ver != PIPEX_L2TP_VER) {
2008 		PIPEX_DBG((NULL, LOG_DEBUG,
2009 		    "<%s> l2tp header wrong version %u.", __func__, ver));
2010 		goto not_ours;
2011 	}
2012 	if ((flags & PIPEX_L2TP_FLAG_TYPE) != 0)
2013 		goto not_ours;
2014 
2015 	if (flags & PIPEX_L2TP_FLAG_LENGTH)
2016 		cp += 2;			/* skip length field */
2017 	cp += 2;				/* skip tunnel-id field */
2018 	GETSHORT(session_id, cp);		/* get session-id field */
2019 
2020 	/* lookup pipex session table */
2021 	session = pipex_lookup_by_session_id(PIPEX_PROTO_L2TP, session_id);
2022 	if (session == NULL) {
2023 		PIPEX_DBG((NULL, LOG_DEBUG,
2024 		    "<%s> session not found (id=%d)", __func__, session_id));
2025 		goto not_ours;
2026 	}
2027 	switch (sasrc->sa_family) {
2028 	case AF_INET:
2029 		if (session->peer.sa.sa_family == AF_INET &&
2030 		    session->peer.sin4.sin_addr.s_addr ==
2031 		    ((struct sockaddr_in *)sasrc)->sin_addr.s_addr)
2032 			srcmatch = 1;
2033 		break;
2034 #ifdef INET6
2035 	case AF_INET6:
2036 		if (session->peer.sa.sa_family == AF_INET6 &&
2037 		    IN6_ARE_ADDR_EQUAL(&session->peer.sin6.sin6_addr,
2038 		    &((struct sockaddr_in6 *)sasrc)->sin6_addr))
2039 			srcmatch = 1;
2040 		break;
2041 #endif
2042 	}
2043 	if (!srcmatch) {
2044 		PIPEX_DBG((NULL, LOG_DEBUG,
2045 		    "<%s> the source address of the session is not matched",
2046 		    __func__));
2047 		pipex_rele_session(session);
2048 		session = NULL;
2049 	}
2050 
2051 	return (session);
2052 
2053 not_ours:
2054 	return (NULL);
2055 }
2056 
2057 struct mbuf *
pipex_l2tp_input(struct mbuf * m0,int off0,struct pipex_session * session,uint32_t ipsecflowinfo)2058 pipex_l2tp_input(struct mbuf *m0, int off0, struct pipex_session *session,
2059     uint32_t ipsecflowinfo)
2060 {
2061 	struct pipex_l2tp_session *l2tp_session;
2062 	int length = 0, offset = 0, hlen, nseq;
2063 	u_char *cp, *nsp = NULL, *nrp = NULL;
2064 	uint16_t flags, ns = 0, nr = 0;
2065 	int rewind = 0;
2066 
2067 	mtx_enter(&session->pxs_mtx);
2068 
2069 	l2tp_session = &session->proto.l2tp;
2070 	if (l2tp_session->ipsecflowinfo > 0 &&
2071 	    l2tp_session->ipsecflowinfo != ipsecflowinfo) {
2072 		pipex_session_log(session, LOG_DEBUG,
2073 		    "received message is %s",
2074 		    (ipsecflowinfo != 0)? "from invalid ipsec flow" :
2075 		    "without ipsec");
2076 		goto drop;
2077 	}
2078 
2079 	m_copydata(m0, off0, sizeof(flags), &flags);
2080 
2081 	flags = ntohs(flags) & PIPEX_L2TP_FLAG_MASK;
2082 	KASSERT((flags & PIPEX_L2TP_FLAG_TYPE) == 0);
2083 
2084 	hlen = 2;				/* flags and version fields */
2085 	if (flags & PIPEX_L2TP_FLAG_LENGTH)	/* length */
2086 		hlen += 2;
2087 	hlen += 4;				/* tunnel-id and session-id */
2088 	if (flags & PIPEX_L2TP_FLAG_SEQUENCE)	/* ns and nr */
2089 		hlen += 4;
2090 	if (flags & PIPEX_L2TP_FLAG_OFFSET)	/* offset */
2091 		hlen += 2;
2092 
2093 	PIPEX_PULLUP(m0, off0 + hlen);
2094 	if (m0  == NULL)
2095 		goto drop;
2096 
2097 	cp = mtod(m0, u_char *) + off0;
2098 	cp += 2;	/* flags and version */
2099 	if (flags & PIPEX_L2TP_FLAG_LENGTH)
2100 		GETSHORT(length, cp);
2101 	else
2102 		length = m0->m_pkthdr.len - off0;
2103 	cp += 4;	/* skip tunnel-id and session-id field */
2104 
2105 	/* pullup for seek sequences in header */
2106 	nseq = 0;
2107 	if (flags & PIPEX_L2TP_FLAG_SEQUENCE) {
2108 		nsp = cp;
2109 		GETSHORT(ns, cp);
2110 		nrp = cp;
2111 		GETSHORT(nr, cp);
2112 
2113 		nr++;
2114 		if (SEQ16_GT(nr, l2tp_session->ns_una) &&
2115 		    SEQ16_LE(nr, l2tp_session->ns_nxt))
2116 			/* update 'ns_una' only if the ns is in valid range */
2117 			l2tp_session->ns_una = nr;
2118 		if (SEQ16_LT(ns, l2tp_session->nr_nxt)) {
2119 			rewind = 1;
2120 			if (SEQ16_LT(ns,
2121 			    l2tp_session->nr_nxt - PIPEX_REWIND_LIMIT))
2122 				goto out_seq;
2123 		}
2124 
2125 		ns++;
2126 		nseq = SEQ16_SUB(ns, l2tp_session->nr_nxt);
2127 		if (!rewind)
2128 			l2tp_session->nr_nxt = ns;
2129 	}
2130 	if (flags & PIPEX_L2TP_FLAG_OFFSET)
2131 		GETSHORT(offset, cp);
2132 
2133 	length -= hlen + offset;
2134 	hlen += off0 + offset;
2135 
2136 	/*
2137 	 * The following pipex_common_input() will release `pxs_mtx'
2138 	 * deep within if the packet will be consumed. In the error
2139 	 * path lock will be held all the time. So increment `nr_gap'
2140 	 * here, and on the error path back it out, no atomicity will
2141 	 * be lost in all cases.
2142 	 */
2143 	if (!rewind)
2144 		session->proto.l2tp.nr_gap += nseq;
2145 	m0 = pipex_common_input(session, m0, hlen, length, 1);
2146 	if (m0 == NULL) {
2147 		/*
2148 		 * pipex_common_input() releases lock if the
2149 		 * packet was consumed.
2150 		 */
2151 		return (NULL);
2152 	}
2153 
2154 	if (rewind)
2155 		goto out_seq;
2156 	else {
2157 		/* The packet is not ours, backout `nr_gap'. */
2158 		session->proto.l2tp.nr_gap -= nseq;
2159 	}
2160 
2161 	/*
2162 	 * overwrite sequence numbers to adjust a gap between pipex and
2163 	 * userland.
2164 	 */
2165 	if (flags & PIPEX_L2TP_FLAG_SEQUENCE) {
2166 		--ns; --nr;	/* revert original values */
2167 		ns -= l2tp_session->nr_gap;
2168 		PUTSHORT(ns, nsp);
2169 
2170 		if (l2tp_session->ns_nxt == l2tp_session->ns_una) {
2171 			nr -= l2tp_session->ns_gap;
2172 			l2tp_session->ul_ns_una = nr;
2173 		} else {
2174 			/*
2175 			 * There are sending packets they are not acked.
2176 			 * In this situation, (ack - snd_gap) may points
2177 			 * before sending window of userland.  So we don't
2178 			 * update the ack number.
2179 			 */
2180 			nr = l2tp_session->ul_ns_una;
2181 		}
2182 		PUTSHORT(nr, nrp);
2183 	}
2184 
2185 	mtx_leave(&session->pxs_mtx);
2186 
2187 	return (m0);
2188 out_seq:
2189 	pipex_session_log(session, LOG_DEBUG,
2190 	    "Received bad data packet: out of sequence: seq=%u(%u-) "
2191 	    "ack=%u(%u-%u)", ns, l2tp_session->nr_nxt, nr, l2tp_session->ns_una,
2192 	    l2tp_session->ns_nxt);
2193 	/* FALLTHROUGH */
2194 drop:
2195 	mtx_leave(&session->pxs_mtx);
2196 
2197 	m_freem(m0);
2198 	counters_inc(session->stat_counters, pxc_ierrors);
2199 
2200 	return (NULL);
2201 }
2202 
2203 struct pipex_session *
pipex_l2tp_userland_lookup_session_ipv4(struct mbuf * m0,struct in_addr dst)2204 pipex_l2tp_userland_lookup_session_ipv4(struct mbuf *m0, struct in_addr dst)
2205 {
2206 	struct sockaddr_in sin;
2207 
2208 	memset(&sin, 0, sizeof(sin));
2209 	sin.sin_len = sizeof(sin);
2210 	sin.sin_family = AF_INET;
2211 	sin.sin_addr = dst;
2212 
2213 	return pipex_l2tp_userland_lookup_session(m0, sintosa(&sin));
2214 }
2215 
2216 #ifdef INET6
2217 struct pipex_session *
pipex_l2tp_userland_lookup_session_ipv6(struct mbuf * m0,struct in6_addr dst)2218 pipex_l2tp_userland_lookup_session_ipv6(struct mbuf *m0, struct in6_addr dst)
2219 {
2220 	struct sockaddr_in6 sin6;
2221 
2222 	memset(&sin6, 0, sizeof(sin6));
2223 	sin6.sin6_len = sizeof(sin6);
2224 	sin6.sin6_family = AF_INET6;
2225 	in6_recoverscope(&sin6, &dst);
2226 
2227 	return pipex_l2tp_userland_lookup_session(m0, sin6tosa(&sin6));
2228 }
2229 #endif
2230 
2231 struct pipex_session *
pipex_l2tp_userland_lookup_session(struct mbuf * m0,struct sockaddr * sa)2232 pipex_l2tp_userland_lookup_session(struct mbuf *m0, struct sockaddr *sa)
2233 {
2234 	struct pipex_l2tp_header l2tp;
2235 	struct pipex_hash_head *list;
2236 	struct pipex_session *session;
2237 	uint16_t session_id, tunnel_id, flags;
2238 
2239 	if (sa->sa_family != AF_INET && sa->sa_family != AF_INET6)
2240 		return (NULL);
2241 
2242 	/* pullup */
2243 	if (m0->m_pkthdr.len < sizeof(l2tp)) {
2244 		PIPEX_DBG((NULL, LOG_DEBUG,
2245 		    "<%s> packet length is too short", __func__));
2246 		return (NULL);
2247 	}
2248 
2249 	/* get flags */
2250 	m_copydata(m0, 0, sizeof(l2tp), &l2tp);
2251 	flags = ntohs(l2tp.flagsver);
2252 
2253 	/* l2tp version must be '2' */
2254 	if ((flags & PIPEX_L2TP_VER_MASK) != PIPEX_L2TP_VER) {
2255 		PIPEX_DBG((NULL, LOG_DEBUG,
2256 		    "<%s> l2tp header wrong version.", __func__));
2257 		return (NULL);
2258 	}
2259 	/* We need L2TP data messages only */
2260 	if ((flags & PIPEX_L2TP_FLAG_TYPE) != 0)
2261 		return (NULL);
2262 	/* No need to hook packets that don't have the sequence field */
2263 	if ((flags & PIPEX_L2TP_FLAG_SEQUENCE) == 0)
2264 		return (NULL);
2265 
2266 	session_id = ntohs(l2tp.session_id);
2267 	tunnel_id = ntohs(l2tp.tunnel_id);
2268 
2269 	mtx_enter(&pipex_list_mtx);
2270 
2271 	list = PIPEX_PEER_ADDR_HASHTABLE(pipex_sockaddr_hash_key(sa));
2272 	LIST_FOREACH(session, list, peer_addr_chain) {
2273 		if (pipex_sockaddr_compar_addr(&session->peer.sa, sa) != 0)
2274 			continue;
2275 		if (session->proto.l2tp.peer_tunnel_id != tunnel_id)
2276 			continue;
2277 		if (session->peer_session_id == session_id)
2278 			break;
2279 	}
2280 
2281 	if (session != NULL)
2282 		refcnt_take(&session->pxs_refcnt);
2283 
2284 	mtx_leave(&pipex_list_mtx);
2285 
2286 #ifdef PIPEX_DEBUG
2287 	if (session == NULL) {
2288 		PIPEX_DBG((NULL, LOG_DEBUG, "<%s> session not found "
2289 		    "(tunnel_id=%d, session_id=%d)", __func__,
2290 		    tunnel_id, session_id));
2291 	}
2292 #endif
2293 
2294 	return (session);
2295 }
2296 
2297 struct mbuf *
pipex_l2tp_userland_output(struct mbuf * m0,struct pipex_session * session)2298 pipex_l2tp_userland_output(struct mbuf *m0, struct pipex_session *session)
2299 {
2300 	struct pipex_l2tp_header *l2tp;
2301 	struct pipex_l2tp_seq_header *seq;
2302 	uint16_t ns, nr;
2303 
2304 	/* check length */
2305 	PIPEX_PULLUP(m0, sizeof(struct pipex_l2tp_header) +
2306 	    sizeof(struct pipex_l2tp_seq_header));
2307 	if (m0 == NULL)
2308 		return (NULL);
2309 
2310 	l2tp = mtod(m0, struct pipex_l2tp_header *);
2311 	KASSERT(ntohs(l2tp->flagsver) & PIPEX_L2TP_FLAG_SEQUENCE);
2312 
2313 	/*
2314 	 * overwrite sequence numbers to adjust a gap between pipex and
2315 	 * userland.
2316 	 */
2317 	seq = (struct pipex_l2tp_seq_header *)(l2tp + 1);
2318 	ns = ntohs(seq->ns);
2319 	nr = ntohs(seq->nr);
2320 
2321 	mtx_enter(&session->pxs_mtx);
2322 
2323 	ns += session->proto.l2tp.ns_gap;
2324 	seq->ns = htons(ns);
2325 	session->proto.l2tp.ns_nxt++;
2326 
2327 	nr += session->proto.l2tp.nr_gap;
2328 	seq->nr = htons(nr);
2329 	if (SEQ16_GT(nr, session->proto.l2tp.nr_acked))
2330 		session->proto.l2tp.nr_acked = nr;
2331 
2332 	mtx_leave(&session->pxs_mtx);
2333 
2334 	return (m0);
2335 }
2336 #endif /* PIPEX_L2TP */
2337 
2338 #ifdef PIPEX_MPPE
2339 /**********************************************************************
2340  * MPPE
2341  ***********************************************************************/
2342 #define	PIPEX_COHERENCY_CNT_MASK		0x0fff
2343 
2344 static inline int
pipex_mppe_setkey(struct pipex_mppe * mppe)2345 pipex_mppe_setkey(struct pipex_mppe *mppe)
2346 {
2347 	rc4_keysetup(&mppe->rc4ctx, mppe->session_key, mppe->keylen);
2348 
2349 	return (0);
2350 }
2351 
2352 static inline int
pipex_mppe_setoldkey(struct pipex_mppe * mppe,uint16_t coher_cnt)2353 pipex_mppe_setoldkey(struct pipex_mppe *mppe, uint16_t coher_cnt)
2354 {
2355 	KASSERT(mppe->old_session_keys != NULL);
2356 
2357 	rc4_keysetup(&mppe->rc4ctx,
2358 	    mppe->old_session_keys[coher_cnt & PIPEX_MPPE_OLDKEYMASK],
2359 	    mppe->keylen);
2360 
2361 	return (0);
2362 }
2363 
2364 static inline void
pipex_mppe_crypt(struct pipex_mppe * mppe,int len,u_char * indata,u_char * outdata)2365 pipex_mppe_crypt(struct pipex_mppe *mppe, int len, u_char *indata,
2366     u_char *outdata)
2367 {
2368 	rc4_crypt(&mppe->rc4ctx, indata, outdata, len);
2369 }
2370 
2371 void
pipex_mppe_init(struct pipex_mppe * mppe,int stateless,int keylenbits,u_char * master_key,int has_oldkey)2372 pipex_mppe_init(struct pipex_mppe *mppe, int stateless, int keylenbits,
2373     u_char *master_key, int has_oldkey)
2374 {
2375 	memset(mppe, 0, sizeof(struct pipex_mppe));
2376 	mtx_init(&mppe->pxm_mtx, IPL_SOFTNET);
2377 	if (stateless)
2378 		mppe->flags |= PIPEX_MPPE_STATELESS;
2379 	if (has_oldkey)
2380 		mppe->old_session_keys =
2381 		    pool_get(&mppe_key_pool, PR_WAITOK);
2382 	else
2383 		mppe->old_session_keys = NULL;
2384 	memcpy(mppe->master_key, master_key, sizeof(mppe->master_key));
2385 
2386 	mppe->keylenbits = keylenbits;
2387 	switch (keylenbits) {
2388 	case 40:
2389 	case 56:
2390 		mppe->keylen = 8;
2391 		break;
2392 	case 128:
2393 		mppe->keylen = 16;
2394 		break;
2395 	}
2396 
2397 	GetNewKeyFromSHA(mppe->master_key, mppe->master_key, mppe->keylen,
2398 	    mppe->session_key);
2399 	pipex_mppe_reduce_key(mppe);
2400 	pipex_mppe_setkey(mppe);
2401 }
2402 
2403 void
pipex_session_init_mppe_recv(struct pipex_session * session,int stateless,int keylenbits,u_char * master_key)2404 pipex_session_init_mppe_recv(struct pipex_session *session, int stateless,
2405     int keylenbits, u_char *master_key)
2406 {
2407 	pipex_mppe_init(&session->mppe_recv, stateless, keylenbits,
2408 	    master_key, stateless);
2409 	session->ppp_flags |= PIPEX_PPP_MPPE_ACCEPTED;
2410 }
2411 
2412 void
pipex_session_init_mppe_send(struct pipex_session * session,int stateless,int keylenbits,u_char * master_key)2413 pipex_session_init_mppe_send(struct pipex_session *session, int stateless,
2414     int keylenbits, u_char *master_key)
2415 {
2416 	pipex_mppe_init(&session->mppe_send, stateless, keylenbits,
2417 	    master_key, 0);
2418 	session->ppp_flags |= PIPEX_PPP_MPPE_ENABLED;
2419 }
2420 
2421 #include <crypto/sha1.h>
2422 
2423 static u_char SHAPad1[] = {
2424 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2425 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2426 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2427 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2428 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2429 }, SHAPad2[] = {
2430 	0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
2431 	0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
2432 	0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
2433 	0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
2434 	0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
2435 };
2436 
2437 void
GetNewKeyFromSHA(u_char * StartKey,u_char * SessionKey,int SessionKeyLength,u_char * InterimKey)2438 GetNewKeyFromSHA(u_char *StartKey, u_char *SessionKey, int SessionKeyLength,
2439     u_char *InterimKey)
2440 {
2441 	u_char Digest[20];
2442 	SHA1_CTX Context;
2443 
2444 	SHA1Init(&Context);
2445 	SHA1Update(&Context, StartKey, SessionKeyLength);
2446 	SHA1Update(&Context, SHAPad1, 40);
2447 	SHA1Update(&Context, SessionKey, SessionKeyLength);
2448 	SHA1Update(&Context, SHAPad2, 40);
2449 	SHA1Final(Digest, &Context);
2450 
2451 	memcpy(InterimKey, Digest, SessionKeyLength);
2452 }
2453 
2454 void
pipex_mppe_reduce_key(struct pipex_mppe * mppe)2455 pipex_mppe_reduce_key(struct pipex_mppe *mppe)
2456 {
2457 	switch (mppe->keylenbits) {
2458 	case 40:
2459 		mppe->session_key[0] = 0xd1;
2460 		mppe->session_key[1] = 0x26;
2461 		mppe->session_key[2] = 0x9e;
2462 		break;
2463 	case 56:
2464 		mppe->session_key[0] = 0xd1;
2465 		break;
2466 	}
2467 }
2468 
2469 void
mppe_key_change(struct pipex_mppe * mppe)2470 mppe_key_change(struct pipex_mppe *mppe)
2471 {
2472 	u_char interim[16];
2473 	struct rc4_ctx keychg;
2474 
2475 	memset(&keychg, 0, sizeof(keychg));
2476 
2477 	GetNewKeyFromSHA(mppe->master_key, mppe->session_key, mppe->keylen,
2478 	    interim);
2479 
2480 	rc4_keysetup(&keychg, interim, mppe->keylen);
2481 	rc4_crypt(&keychg, interim, mppe->session_key, mppe->keylen);
2482 
2483 	pipex_mppe_reduce_key(mppe);
2484 
2485 	if (mppe->old_session_keys) {
2486 		int idx = mppe->coher_cnt & PIPEX_MPPE_OLDKEYMASK;
2487 		memcpy(mppe->old_session_keys[idx],
2488 		    mppe->session_key, PIPEX_MPPE_KEYLEN);
2489 	}
2490 }
2491 
2492 struct mbuf *
pipex_mppe_input(struct mbuf * m0,struct pipex_session * session)2493 pipex_mppe_input(struct mbuf *m0, struct pipex_session *session)
2494 {
2495 	int pktloss, encrypt, flushed, m, n, len;
2496 	struct pipex_mppe *mppe;
2497 	uint16_t coher_cnt;
2498 	struct mbuf *m1;
2499 	u_char *cp;
2500 	int rewind = 0;
2501 
2502 	/* pullup */
2503 	PIPEX_PULLUP(m0, sizeof(coher_cnt));
2504 	if (m0 == NULL)
2505 		goto drop;
2506 
2507 	mppe = &session->mppe_recv;
2508 	/* get header information */
2509 	cp = mtod(m0, u_char *);
2510 	GETSHORT(coher_cnt, cp);
2511 	flushed = ((coher_cnt & 0x8000) != 0) ? 1 : 0;
2512 	encrypt = ((coher_cnt & 0x1000) != 0) ? 1 : 0;
2513 	coher_cnt &= PIPEX_COHERENCY_CNT_MASK;
2514 	pktloss = 0;
2515 
2516 	mtx_enter(&mppe->pxm_mtx);
2517 
2518 	PIPEX_MPPE_DBG((session, LOG_DEBUG, "in coher_cnt=%03x %s%s",
2519 	    mppe->coher_cnt, (flushed) ? "[flushed]" : "",
2520 	    (encrypt) ? "[encrypt]" : ""));
2521 
2522 	if (encrypt == 0) {
2523 		mtx_leave(&mppe->pxm_mtx);
2524 		pipex_session_log(session, LOG_DEBUG,
2525 		    "Received unexpected MPPE packet.(no ecrypt)");
2526 		goto drop;
2527 	}
2528 
2529 	/* adjust mbuf */
2530 	m_adj(m0, sizeof(coher_cnt));
2531 
2532 	/*
2533 	 * L2TP data session may be used without sequencing, PPP frames may
2534 	 * arrive in disorder.  The 'coherency counter' of MPPE detects such
2535 	 * situations, but we cannot distinguish between 'disorder' and
2536 	 * 'packet loss' exactly.
2537 	 *
2538 	 * When 'coherency counter' detects lost packets greater than
2539 	 * (4096 - 256), we treat as 'disorder' otherwise treat as
2540 	 * 'packet loss'.
2541 	 */
2542     {
2543 	int coher_cnt0;
2544 
2545 	coher_cnt0 = coher_cnt;
2546 	if (coher_cnt < mppe->coher_cnt)
2547 		coher_cnt0 += 0x1000;
2548 	if (coher_cnt0 - mppe->coher_cnt > 0x0f00) {
2549 		if ((mppe->flags & PIPEX_MPPE_STATELESS) == 0 ||
2550 		    coher_cnt0 - mppe->coher_cnt
2551 		    <= 0x1000 - PIPEX_MPPE_NOLDKEY) {
2552 			pipex_session_log(session, LOG_DEBUG,
2553 			    "Workaround the out-of-sequence PPP framing problem: "
2554 			    "%d => %d", mppe->coher_cnt, coher_cnt);
2555 			mtx_leave(&mppe->pxm_mtx);
2556 			goto drop;
2557 		}
2558 		rewind = 1;
2559 	}
2560     }
2561 
2562 	if ((mppe->flags & PIPEX_MPPE_STATELESS) != 0) {
2563 		if (!rewind) {
2564 			mppe_key_change(mppe);
2565 			while (mppe->coher_cnt != coher_cnt) {
2566 				mppe->coher_cnt++;
2567 				mppe->coher_cnt &= PIPEX_COHERENCY_CNT_MASK;
2568 				mppe_key_change(mppe);
2569 				pktloss++;
2570 			}
2571 		}
2572 		pipex_mppe_setoldkey(mppe, coher_cnt);
2573 	} else {
2574 		if (flushed) {
2575 			if (coher_cnt < mppe->coher_cnt) {
2576 				coher_cnt += 0x1000;
2577 			}
2578 			pktloss += coher_cnt - mppe->coher_cnt;
2579 			m = mppe->coher_cnt / 256;
2580 			n = coher_cnt / 256;
2581 			while (m++ < n)
2582 				mppe_key_change(mppe);
2583 
2584 			coher_cnt &= PIPEX_COHERENCY_CNT_MASK;
2585 			mppe->coher_cnt = coher_cnt;
2586 		} else if (mppe->coher_cnt != coher_cnt) {
2587 			int ccp_id;
2588 
2589 			mtx_leave(&mppe->pxm_mtx);
2590 
2591 			/* Send CCP ResetReq */
2592 			PIPEX_DBG((session, LOG_DEBUG, "CCP SendResetReq"));
2593 
2594 			mtx_enter(&session->pxs_mtx);
2595 			ccp_id = session->ccp_id;
2596 			session->ccp_id++;
2597 			mtx_leave(&session->pxs_mtx);
2598 
2599 			pipex_ccp_output(session, CCP_RESETREQ, ccp_id);
2600 			goto drop;
2601 		}
2602 		if ((coher_cnt & 0xff) == 0xff) {
2603 			mppe_key_change(mppe);
2604 			flushed = 1;
2605 		}
2606 		if (flushed)
2607 			pipex_mppe_setkey(mppe);
2608 	}
2609 
2610 	if (pktloss > 1000) {
2611 		pipex_session_log(session, LOG_DEBUG,
2612 		    "%d packets loss.", pktloss);
2613 	}
2614 
2615 	/* decrypt ppp payload */
2616 	for (m1 = m0; m1; m1 = m1->m_next) {
2617 		cp = mtod(m1, u_char *);
2618 		len = m1->m_len;
2619 		pipex_mppe_crypt(mppe, len, cp, cp);
2620 	}
2621 
2622 	if (!rewind) {
2623 		/* update coher_cnt */
2624 		mppe->coher_cnt++;
2625 		mppe->coher_cnt &= PIPEX_COHERENCY_CNT_MASK;
2626 	}
2627 
2628 	mtx_leave(&mppe->pxm_mtx);
2629 
2630 	if (m0->m_pkthdr.len < PIPEX_PPPMINLEN)
2631 		goto drop;
2632 
2633 	return (m0);
2634 drop:
2635 	m_freem(m0);
2636 	return (NULL);
2637 }
2638 
2639 struct mbuf *
pipex_mppe_output(struct mbuf * m0,struct pipex_session * session,uint16_t protocol)2640 pipex_mppe_output(struct mbuf *m0, struct pipex_session *session,
2641     uint16_t protocol)
2642 {
2643 	int encrypt, flushed, len;
2644 	struct mppe_header {
2645 		uint16_t coher_cnt;
2646 		uint16_t protocol;
2647 	} __packed *hdr;
2648 	u_char *cp;
2649 	struct pipex_mppe *mppe;
2650 	struct mbuf *m;
2651 
2652 	mppe = &session->mppe_send;
2653 
2654 	/*
2655 	 * create a deep-copy if the mbuf has a shared mbuf cluster.
2656 	 * this is required to handle cases of tcp retransmission.
2657 	 */
2658 	for (m = m0; m != NULL; m = m->m_next) {
2659 		if (M_READONLY(m)) {
2660 			m = m_dup_pkt(m0, max_linkhdr, M_NOWAIT);
2661 			m_freem(m0);
2662 			if (m == NULL)
2663 				return (NULL);
2664 			m0 = m;
2665 			break;
2666 		}
2667 	}
2668 	/* prepend mppe header */
2669 	M_PREPEND(m0, sizeof(struct mppe_header), M_NOWAIT);
2670 	if (m0 == NULL)
2671 		return (NULL);
2672 	hdr = mtod(m0, struct mppe_header *);
2673 	hdr->protocol = protocol;
2674 
2675 	/* check coherency counter */
2676 	flushed = 0;
2677 	encrypt = 1;
2678 
2679 	mtx_enter(&mppe->pxm_mtx);
2680 
2681 	if ((mppe->flags & PIPEX_MPPE_STATELESS) != 0) {
2682 		flushed = 1;
2683 		mppe_key_change(mppe);
2684 	} else {
2685 		if ((mppe->coher_cnt % 0x100) == 0xff) {
2686 			flushed = 1;
2687 			mppe_key_change(mppe);
2688 		} else if ((mppe->flags & PIPEX_MPPE_RESETREQ) != 0) {
2689 			flushed = 1;
2690 			mppe->flags &= ~PIPEX_MPPE_RESETREQ;
2691 		}
2692 	}
2693 
2694 	if (flushed)
2695 		pipex_mppe_setkey(mppe);
2696 
2697 	PIPEX_MPPE_DBG((session, LOG_DEBUG, "out coher_cnt=%03x %s%s",
2698 	    mppe->coher_cnt, (flushed) ? "[flushed]" : "",
2699 	    (encrypt) ? "[encrypt]" : ""));
2700 
2701 	/* setup header information */
2702 	hdr->coher_cnt = (mppe->coher_cnt++) & PIPEX_COHERENCY_CNT_MASK;
2703 	hdr->coher_cnt &= PIPEX_COHERENCY_CNT_MASK;
2704 	if (flushed)
2705 		hdr->coher_cnt |= 0x8000;
2706 	if (encrypt)
2707 		hdr->coher_cnt |= 0x1000;
2708 
2709 	hdr->protocol = htons(hdr->protocol);
2710 	hdr->coher_cnt = htons(hdr->coher_cnt);
2711 
2712 	/* encrypt chain */
2713 	for (m = m0; m; m = m->m_next) {
2714 		cp = mtod(m, u_char *);
2715 		len = m->m_len;
2716 		if (m == m0 && len > offsetof(struct mppe_header, protocol)) {
2717 			len -= offsetof(struct mppe_header, protocol);
2718 			cp += offsetof(struct mppe_header, protocol);
2719 		}
2720 		pipex_mppe_crypt(mppe, len, cp, cp);
2721 	}
2722 
2723 	mtx_leave(&mppe->pxm_mtx);
2724 
2725 	return (m0);
2726 }
2727 
2728 void
pipex_ccp_input(struct mbuf * m0,struct pipex_session * session)2729 pipex_ccp_input(struct mbuf *m0, struct pipex_session *session)
2730 {
2731 	u_char *cp;
2732 	int code, id, len;
2733 
2734 	if (m0->m_pkthdr.len < PPP_HDRLEN)
2735 		goto drop;
2736 	if ((m0 = m_pullup(m0, PPP_HDRLEN)) == NULL)
2737 		goto drop;
2738 
2739 	cp = mtod(m0, u_char *);
2740 	GETCHAR(code, cp);
2741 	GETCHAR(id, cp);
2742 	GETSHORT(len, cp);
2743 
2744 	switch (code) {
2745 	case CCP_RESETREQ:
2746 		PIPEX_DBG((session, LOG_DEBUG, "CCP RecvResetReq"));
2747 		mtx_enter(&session->mppe_send.pxm_mtx);
2748 		session->mppe_send.flags |= PIPEX_MPPE_RESETREQ;
2749 		mtx_leave(&session->mppe_send.pxm_mtx);
2750 #ifndef PIPEX_NO_CCP_RESETACK
2751 		PIPEX_DBG((session, LOG_DEBUG, "CCP SendResetAck"));
2752 		pipex_ccp_output(session, CCP_RESETACK, id);
2753 #endif
2754 		/* ignore error */
2755 		break;
2756 	case CCP_RESETACK:
2757 		PIPEX_DBG((session, LOG_DEBUG, "CCP RecvResetAck"));
2758 		break;
2759 	default:
2760 		PIPEX_DBG((session, LOG_DEBUG, "CCP Recv code=%d", code));
2761 		goto drop;
2762 	}
2763 	m_freem(m0);
2764 
2765 	return;
2766 drop:
2767 	m_freem(m0);
2768 	counters_inc(session->stat_counters, pxc_ierrors);
2769 }
2770 
2771 int
pipex_ccp_output(struct pipex_session * session,int code,int id)2772 pipex_ccp_output(struct pipex_session *session, int code, int id)
2773 {
2774 	u_char *cp;
2775 	struct mbuf *m;
2776 
2777 	MGETHDR(m, M_DONTWAIT, MT_DATA);
2778 	if (m == NULL) {
2779 		counters_inc(session->stat_counters, pxc_oerrors);
2780 		return (1);
2781 	}
2782 	m->m_pkthdr.len = m->m_len = 4;
2783 	cp = mtod(m, u_char *);
2784 	PUTCHAR(code, cp);
2785 	PUTCHAR(id, cp);
2786 	PUTSHORT(4, cp);
2787 
2788 	pipex_ppp_output(m, session, PPP_CCP);
2789 
2790 	return (0);
2791 }
2792 #endif
2793 /***********************************************************************
2794  * Miscellaneous functions
2795  ***********************************************************************/
2796 /* adapted from FreeBSD:src/usr.sbin/ppp/tcpmss.c */
2797 /*
2798  * Copyright (c) 2000 Ruslan Ermilov and Brian Somers <brian@Awfulhak.org>
2799  * All rights reserved.
2800  *
2801  * Redistribution and use in source and binary forms, with or without
2802  * modification, are permitted provided that the following conditions
2803  * are met:
2804  * 1. Redistributions of source code must retain the above copyright
2805  *    notice, this list of conditions and the following disclaimer.
2806  * 2. Redistributions in binary form must reproduce the above copyright
2807  *    notice, this list of conditions and the following disclaimer in the
2808  *    documentation and/or other materials provided with the distribution.
2809  *
2810  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
2811  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2812  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2813  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2814  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2815  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2816  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2817  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2818  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2819  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2820  * SUCH DAMAGE.
2821  *
2822  * $FreeBSD: src/usr.sbin/ppp/tcpmss.c,v 1.1.4.3 2001/07/19 11:39:54 brian Exp $
2823  */
2824 #define TCP_OPTLEN_IN_SEGMENT	12	/* timestamp option and padding */
2825 #define MAXMSS(mtu) (mtu - sizeof(struct ip) - sizeof(struct tcphdr) - \
2826     TCP_OPTLEN_IN_SEGMENT)
2827 /*
2828  * The following macro is used to update an internet checksum.  "acc" is a
2829  * 32-bit accumulation of all the changes to the checksum (adding in old
2830  * 16-bit words and subtracting out new words), and "cksum" is the checksum
2831  * value to be updated.
2832  */
2833 #define ADJUST_CHECKSUM(acc, cksum) {			\
2834 	acc += cksum;					\
2835 	if (acc < 0) {					\
2836 		acc = -acc;				\
2837 		acc = (acc >> 16) + (acc & 0xffff);	\
2838 		acc += acc >> 16;			\
2839 		cksum = (u_short) ~acc;			\
2840 	} else {					\
2841 		acc = (acc >> 16) + (acc & 0xffff);	\
2842 		acc += acc >> 16;			\
2843 		cksum = (u_short) acc;			\
2844 	}						\
2845 }
2846 
2847 /*
2848  * Rewrite max-segment-size TCP option to avoid PMTU blackhole issues.
2849  * The mtu parameter should be the MTU bottleneck (as far as we know)
2850  * on the link between the source and the destination.
2851  */
2852 struct mbuf *
adjust_tcp_mss(struct mbuf * m0,int mtu)2853 adjust_tcp_mss(struct mbuf *m0, int mtu)
2854 {
2855 	int opt, optlen, acc, mss, maxmss, lpktp;
2856 	struct ip *pip;
2857 	struct tcphdr *th;
2858 	u_char *pktp, *mssp;
2859 	u_int16_t ip_off;
2860 
2861 	lpktp = sizeof(struct ip) + sizeof(struct tcphdr) + PIPEX_TCP_OPTLEN;
2862 	lpktp = MIN(lpktp, m0->m_pkthdr.len);
2863 
2864 	PIPEX_PULLUP(m0, lpktp);
2865 	if (m0 == NULL)
2866 		goto drop;
2867 
2868 	pktp = mtod(m0, char *);
2869 	pip = (struct ip *)pktp;
2870 	ip_off = ntohs(pip->ip_off);
2871 
2872 	/* Non TCP or fragmented packet must not have a MSS option */
2873 	if (pip->ip_p != IPPROTO_TCP ||
2874 	    (ip_off & IP_MF) != 0 || (ip_off & IP_OFFMASK) != 0)
2875 		goto handled;
2876 
2877 	pktp += pip->ip_hl << 2;
2878 	lpktp -= pip->ip_hl << 2;
2879 
2880 	/* packet is broken */
2881 	if (sizeof(struct tcphdr) > lpktp)
2882 		goto drop;
2883 	th = (struct tcphdr *)pktp;
2884 
2885 	/*
2886 	 * As RFC 973, a MSS field must only be sent in the initial
2887 	 * connection request(it must be with SYN).
2888 	 */
2889 	if ((th->th_flags & TH_SYN) == 0)
2890 		goto handled;
2891 
2892 	lpktp = MIN(th->th_off << 4, lpktp);
2893 
2894 	pktp += sizeof(struct tcphdr);
2895 	lpktp -= sizeof(struct tcphdr);
2896 	while (lpktp >= TCPOLEN_MAXSEG) {
2897 		GETCHAR(opt, pktp);
2898 		switch (opt) {
2899 		case TCPOPT_MAXSEG:
2900 			GETCHAR(optlen, pktp);
2901 			mssp = pktp;		/* mss place holder */
2902 			GETSHORT(mss, pktp);
2903 			maxmss = MAXMSS(mtu);
2904 			if (mss > maxmss) {
2905 				PIPEX_DBG((NULL, LOG_DEBUG,
2906 				    "change tcp-mss %d => %d", mss, maxmss));
2907 				PUTSHORT(maxmss, mssp);
2908 				acc = htons(mss);
2909 				acc -= htons(maxmss);
2910 				ADJUST_CHECKSUM(acc, th->th_sum);
2911 			}
2912 			goto handled;
2913 			/* NOTREACHED */
2914 		case TCPOPT_EOL:
2915 			goto handled;
2916 			/* NOTREACHED */
2917 		case TCPOPT_NOP:
2918 			lpktp--;
2919 			break;
2920 		default:
2921 			GETCHAR(optlen, pktp);
2922 			if (optlen < 2)	/* packet is broken */
2923 				goto drop;
2924 			pktp += optlen - 2;
2925 			lpktp -= optlen;
2926 			break;
2927 		}
2928 	}
2929 
2930 handled:
2931 	return (m0);
2932 
2933 drop:
2934 	m_freem(m0);
2935 	return (NULL);
2936 }
2937 
2938 /*
2939  *  Check whether a packet should reset idle timer
2940  *  Returns 1 to don't reset timer (i.e. the packet is "idle" packet)
2941  */
2942 struct mbuf *
ip_is_idle_packet(struct mbuf * m0,int * ris_idle)2943 ip_is_idle_packet(struct mbuf *m0, int *ris_idle)
2944 {
2945 	u_int16_t ip_off;
2946 	const struct udphdr *uh;
2947 	struct ip *pip;
2948 	int len;
2949 
2950 	/* pullup ip header */
2951 	len = sizeof(struct ip);
2952 	PIPEX_PULLUP(m0, len);
2953 	if (m0 == NULL)
2954 		goto error;
2955 	pip = mtod(m0, struct ip *);
2956 
2957 	/*
2958 	 * the packet which fragmentations was not the idle packet.
2959 	 */
2960 	ip_off = ntohs(pip->ip_off);
2961 	if ((ip_off & IP_MF) || ((ip_off & IP_OFFMASK) != 0))
2962 		goto is_active;
2963 
2964 	switch (pip->ip_p) {
2965 	case IPPROTO_IGMP:
2966 		goto is_active;
2967 	case IPPROTO_ICMP:
2968 		len = pip->ip_hl * 4 + 8;
2969 		PIPEX_PULLUP(m0, len);
2970 		if (m0 == NULL)
2971 			goto error;
2972 		pip = mtod(m0, struct ip *);
2973 
2974 		switch (((unsigned char *) pip)[pip->ip_hl * 4]) {
2975 		case 0:	/* Echo Reply */
2976 		case 8:	/* Echo Request */
2977 			goto is_active;
2978 		default:
2979 			goto is_idle;
2980 		}
2981 
2982 	case IPPROTO_UDP:
2983 	case IPPROTO_TCP:
2984 		len = pip->ip_hl * 4 + sizeof(struct udphdr);
2985 		PIPEX_PULLUP(m0, len);
2986 		if (m0 == NULL)
2987 			goto error;
2988 		pip = mtod(m0, struct ip *);
2989 		uh = (struct udphdr *)(mtod(m0, caddr_t) + pip->ip_hl * 4);
2990 
2991 		switch (ntohs(uh->uh_sport)) {
2992 		case 53:	/* DOMAIN */
2993 		case 67:	/* BOOTPS */
2994 		case 68:	/* BOOTPC */
2995 		case 123:	/* NTP */
2996 		case 137:	/* NETBIOS-NS */
2997 		case 520:	/* RIP */
2998 			goto is_idle;
2999 		}
3000 		switch (ntohs(uh->uh_dport)) {
3001 		case 53:	/* DOMAIN */
3002 		case 67:	/* BOOTPS */
3003 		case 68:	/* BOOTPC */
3004 		case 123:	/* NTP */
3005 		case 137:	/* NETBIOS-NS */
3006 		case 520:	/* RIP */
3007 			goto is_idle;
3008 		}
3009 		goto is_active;
3010 	default:
3011 		goto is_active;
3012 	}
3013 
3014 is_active:
3015 	*ris_idle = 0;
3016 	return (m0);
3017 
3018 is_idle:
3019 	*ris_idle = 1;
3020 	return (m0);
3021 
3022 error:
3023 	return (NULL);
3024 }
3025 
3026 void
pipex_session_log(struct pipex_session * session,int prio,const char * fmt,...)3027 pipex_session_log(struct pipex_session *session, int prio, const char *fmt, ...)
3028 {
3029 	char logbuf[1024];
3030 	va_list ap;
3031 
3032 	logpri(prio);
3033 	if (session != NULL) {
3034 		struct ifnet *ifp;
3035 
3036 		ifp = if_get(session->ifindex);
3037 		addlog("pipex: ppp=%d iface=%s protocol=%s id=%d ",
3038 		    session->ppp_id,
3039 		    ifp? ifp->if_xname : "Unknown",
3040 		    (session->protocol == PIPEX_PROTO_PPPOE)? "PPPoE" :
3041 		    (session->protocol == PIPEX_PROTO_PPTP)? "PPTP" :
3042 		    (session->protocol == PIPEX_PROTO_L2TP) ? "L2TP" :
3043 		    "Unknown", session->session_id);
3044 		if_put(ifp);
3045 	} else
3046 		addlog("pipex: ");
3047 
3048 	va_start(ap, fmt);
3049 	vsnprintf(logbuf, sizeof(logbuf), fmt, ap);
3050 	va_end(ap);
3051 	addlog("%s\n", logbuf);
3052 }
3053 
3054 uint32_t
pipex_sockaddr_hash_key(struct sockaddr * sa)3055 pipex_sockaddr_hash_key(struct sockaddr *sa)
3056 {
3057 	switch (sa->sa_family) {
3058 	case AF_INET:
3059 		return ntohl(satosin(sa)->sin_addr.s_addr);
3060 	case AF_INET6:
3061 		return ntohl(satosin6(sa)->sin6_addr.s6_addr32[3]);
3062 	}
3063 	panic("pipex_sockaddr_hash_key: unknown address family");
3064 	return (0);
3065 }
3066 
3067 /*
3068  * Compare struct sockaddr_in{,6} with the address only.
3069  * The port number is not covered.
3070  */
3071 int
pipex_sockaddr_compar_addr(struct sockaddr * a,struct sockaddr * b)3072 pipex_sockaddr_compar_addr(struct sockaddr *a, struct sockaddr *b)
3073 {
3074 	int cmp;
3075 
3076 	cmp = b->sa_family - a->sa_family;
3077 	if (cmp != 0)
3078 		return cmp;
3079 	switch (a->sa_family) {
3080 	case AF_INET:
3081 		return (satosin(b)->sin_addr.s_addr -
3082 		    satosin(a)->sin_addr.s_addr);
3083 	case AF_INET6:
3084 		cmp = (satosin6(b)->sin6_scope_id - satosin6(a)->sin6_scope_id);
3085 		if (cmp != 0)
3086 			return cmp;
3087 		return (memcmp(&satosin6(a)->sin6_addr,
3088 		    &satosin6(b)->sin6_addr,
3089 		    sizeof(struct in6_addr)));
3090 	}
3091 	panic("pipex_sockaddr_compar_addr: unknown address family");
3092 
3093 	return (-1);
3094 }
3095 
3096 int
pipex_sysctl(int * name,u_int namelen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)3097 pipex_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
3098     size_t newlen)
3099 {
3100 	switch (name[0]) {
3101 	case PIPEXCTL_ENABLE:
3102 		if (namelen != 1)
3103 			return (ENOTDIR);
3104 		return (sysctl_int_bounded(oldp, oldlenp, newp, newlen,
3105 		    &pipex_enable, 0, 1));
3106 	default:
3107 		return (ENOPROTOOPT);
3108 	}
3109 	/* NOTREACHED */
3110 }
3111