xref: /openbsd/sys/net/pipex.c (revision f168c03c)
1 /*	$OpenBSD: pipex.c,v 1.157 2025/01/25 02:06:40 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 
1278 	/* short packet */
1279 	if (m0->m_pkthdr.len < (sizeof(struct ether_header) + sizeof(pppoe)))
1280 		return (NULL);
1281 
1282 	m_copydata(m0, sizeof(struct ether_header),
1283 	    sizeof(struct pipex_pppoe_header), &pppoe);
1284 	pppoe.session_id = ntohs(pppoe.session_id);
1285 	session = pipex_lookup_by_session_id(PIPEX_PROTO_PPPOE,
1286 	    pppoe.session_id);
1287 #ifdef PIPEX_DEBUG
1288 	if (session == NULL)
1289 		PIPEX_DBG((NULL, LOG_DEBUG, "<%s> session not found (id=%d)",
1290 		    __func__, pppoe.session_id));
1291 #endif
1292 	if (session && session->proto.pppoe.over_ifidx !=
1293 	    m0->m_pkthdr.ph_ifidx) {
1294 		pipex_rele_session(session);
1295 		session = NULL;
1296 	}
1297 
1298 	return (session);
1299 }
1300 
1301 struct mbuf *
pipex_pppoe_input(struct mbuf * m0,struct pipex_session * session)1302 pipex_pppoe_input(struct mbuf *m0, struct pipex_session *session)
1303 {
1304 	int hlen;
1305 	struct pipex_pppoe_header pppoe;
1306 
1307 	/* already checked at pipex_pppoe_lookup_session */
1308 	KASSERT(m0->m_pkthdr.len >= (sizeof(struct ether_header) +
1309 	    sizeof(pppoe)));
1310 
1311 	m_copydata(m0, sizeof(struct ether_header),
1312 	    sizeof(struct pipex_pppoe_header), &pppoe);
1313 
1314 	hlen = sizeof(struct ether_header) + sizeof(struct pipex_pppoe_header);
1315 	m0 = pipex_common_input(session, m0, hlen, ntohs(pppoe.length), 0);
1316 	if (m0 == NULL)
1317 		return (NULL);
1318 	m_freem(m0);
1319 	counters_inc(session->stat_counters, pxc_ierrors);
1320 	return (NULL);
1321 }
1322 
1323 /*
1324  * pipex_ppope_output
1325  */
1326 void
pipex_pppoe_output(struct mbuf * m0,struct pipex_session * session)1327 pipex_pppoe_output(struct mbuf *m0, struct pipex_session *session)
1328 {
1329 	struct pipex_pppoe_header *pppoe;
1330 	int len, padlen;
1331 
1332 	/* save length for pppoe header */
1333 	len = m0->m_pkthdr.len;
1334 
1335 	/* prepend protocol header */
1336 	M_PREPEND(m0, sizeof(struct pipex_pppoe_header), M_NOWAIT);
1337 	if (m0 == NULL) {
1338 		PIPEX_DBG((NULL, LOG_ERR,
1339 		    "<%s> cannot prepend header.", __func__));
1340 		counters_inc(session->stat_counters, pxc_oerrors);
1341 		return;
1342 	}
1343 	padlen = ETHERMIN - m0->m_pkthdr.len;
1344 	if (padlen > 0)
1345 		m_copyback(m0, m0->m_pkthdr.len, padlen, pipex_pppoe_padding,
1346 		    M_NOWAIT);
1347 
1348 	/* setup pppoe header information */
1349 	pppoe = mtod(m0, struct pipex_pppoe_header *);
1350 	pppoe->vertype = PIPEX_PPPOE_VERTYPE;
1351 	pppoe->code = PIPEX_PPPOE_CODE_SESSION;
1352 	pppoe->session_id = htons(session->session_id);
1353 	pppoe->length = htons(len);
1354 
1355 	m0->m_pkthdr.ph_ifidx = session->proto.pppoe.over_ifidx;
1356 	refcnt_take(&session->pxs_refcnt);
1357 	m0->m_pkthdr.ph_cookie = session;
1358 	m0->m_flags &= ~(M_BCAST|M_MCAST);
1359 
1360 	if (mq_enqueue(&pipexoutq, m0) != 0) {
1361 		counters_inc(session->stat_counters, pxc_oerrors);
1362 		pipex_rele_session(session);
1363 	} else
1364 		schednetisr(NETISR_PIPEX);
1365 }
1366 #endif /* PIPEX_PPPOE */
1367 
1368 #ifdef PIPEX_PPTP
1369 /***********************************************************************
1370  * PPTP
1371  ***********************************************************************/
1372 void
pipex_pptp_output(struct mbuf * m0,struct pipex_session * session,int has_seq,int has_ack)1373 pipex_pptp_output(struct mbuf *m0, struct pipex_session *session,
1374     int has_seq, int has_ack)
1375 {
1376 	int len, reqlen;
1377 	struct pipex_gre_header *gre = NULL;
1378 	struct ip *ip;
1379 	u_char *cp;
1380 
1381 	MUTEX_ASSERT_LOCKED(&session->pxs_mtx);
1382 
1383 	reqlen = PIPEX_IPGRE_HDRLEN + (has_seq + has_ack) * 4;
1384 
1385 	len = 0;
1386 	if (m0 != NULL) {
1387 		/* save length for gre header */
1388 		len = m0->m_pkthdr.len;
1389 		/* prepend protocol header */
1390 		M_PREPEND(m0, reqlen, M_NOWAIT);
1391 		if (m0 == NULL)
1392 			goto drop;
1393 	} else {
1394 		MGETHDR(m0, M_DONTWAIT, MT_DATA);
1395 		if (m0 && reqlen > MHLEN) {
1396 			MCLGET(m0, M_DONTWAIT);
1397 			if ((m0->m_flags & M_EXT) == 0) {
1398 				m_freem(m0);
1399 				m0 = NULL;
1400 			}
1401 		}
1402 		if (m0 == NULL)
1403 			goto drop;
1404 		m0->m_pkthdr.len = m0->m_len = reqlen;
1405 	}
1406 
1407 	/* setup ip header information */
1408 	ip = mtod(m0, struct ip *);
1409 
1410 	ip->ip_len = htons(m0->m_pkthdr.len);
1411 	ip->ip_off = 0;
1412 	ip->ip_ttl = MAXTTL;
1413 	ip->ip_p = IPPROTO_GRE;
1414 	ip->ip_tos = 0;
1415 
1416 	ip->ip_src = session->local.sin4.sin_addr;
1417 	ip->ip_dst = session->peer.sin4.sin_addr;
1418 #if NPF > 0
1419 	pf_pkt_addr_changed(m0);
1420 #endif
1421 
1422 	/* setup gre(ver1) header information */
1423 	gre = PIPEX_SEEK_NEXTHDR(ip, sizeof(struct ip),
1424 	    struct pipex_gre_header *);
1425 	gre->type = htons(PIPEX_GRE_PROTO_PPP);
1426 	gre->call_id = htons(session->peer_session_id);
1427 	gre->flags = PIPEX_GRE_KFLAG | PIPEX_GRE_VER;	/* do htons later */
1428 	gre->len = htons(len);
1429 
1430 	cp = PIPEX_SEEK_NEXTHDR(gre, sizeof(struct pipex_gre_header),u_char *);
1431 	if (has_seq) {
1432 		gre->flags |= PIPEX_GRE_SFLAG;
1433 		PUTLONG(session->proto.pptp.snd_nxt, cp);
1434 		session->proto.pptp.snd_nxt++;
1435 		session->proto.pptp.snd_gap++;
1436 	}
1437 	if (has_ack) {
1438 		gre->flags |= PIPEX_GRE_AFLAG;
1439 		session->proto.pptp.rcv_acked = session->proto.pptp.rcv_nxt - 1;
1440 		PUTLONG(session->proto.pptp.rcv_acked, cp);
1441 	}
1442 	gre->flags = htons(gre->flags);
1443 
1444 	m0->m_pkthdr.ph_ifidx = session->ifindex;
1445 	ip_send(m0);
1446 	if (len > 0) {	/* network layer only */
1447 		/* countup statistics */
1448 		counters_pkt(session->stat_counters, pxc_opackets,
1449 		    pxc_obytes, len);
1450 	}
1451 
1452 	return;
1453 drop:
1454 	counters_inc(session->stat_counters, pxc_oerrors);
1455 }
1456 
1457 struct pipex_session *
pipex_pptp_lookup_session(struct mbuf * m0)1458 pipex_pptp_lookup_session(struct mbuf *m0)
1459 {
1460 	struct pipex_session *session;
1461 	struct pipex_gre_header gre;
1462 	struct ip ip;
1463 	uint16_t flags;
1464 	uint16_t id;
1465 	int hlen;
1466 
1467 	if (m0->m_pkthdr.len < PIPEX_IPGRE_HDRLEN) {
1468 		PIPEX_DBG((NULL, LOG_DEBUG,
1469 		    "<%s> packet length is too short", __func__));
1470 		goto not_ours;
1471 	}
1472 
1473 	/* get ip header info */
1474 	m_copydata(m0, 0, sizeof(struct ip), &ip);
1475 	hlen = ip.ip_hl << 2;
1476 
1477 	/*
1478 	 * m0 has already passed ip_input(), so there is
1479 	 * no necessity for ip packet inspection.
1480 	 */
1481 
1482 	/* get gre flags */
1483 	m_copydata(m0, hlen, sizeof(gre), &gre);
1484 	flags = ntohs(gre.flags);
1485 
1486 	/* gre version must be '1' */
1487 	if ((flags & PIPEX_GRE_VERMASK) != PIPEX_GRE_VER) {
1488 		PIPEX_DBG((NULL, LOG_DEBUG,
1489 		    "<%s> gre header wrong version.", __func__));
1490 		goto not_ours;
1491 	}
1492 
1493 	/* gre keys must be present */
1494 	if ((flags & PIPEX_GRE_KFLAG) == 0) {
1495 		PIPEX_DBG((NULL, LOG_DEBUG,
1496 		    "<%s> gre header has no keys.", __func__));
1497 		goto not_ours;
1498 	}
1499 
1500 	/* flag check */
1501 	if ((flags & PIPEX_GRE_UNUSEDFLAGS) != 0) {
1502 		PIPEX_DBG((NULL, LOG_DEBUG,
1503 		    "<%s> gre header has unused flags at pptp.", __func__));
1504 		goto not_ours;
1505 	}
1506 
1507 	/* lookup pipex session table */
1508 	id = ntohs(gre.call_id);
1509 	session = pipex_lookup_by_session_id(PIPEX_PROTO_PPTP, id);
1510 	if (session == NULL) {
1511 		PIPEX_DBG((NULL, LOG_DEBUG,
1512 		    "<%s> session not found (id=%d)", __func__, id));
1513 		goto not_ours;
1514 	}
1515 
1516 	if (!(session->peer.sa.sa_family == AF_INET &&
1517 	    session->peer.sin4.sin_addr.s_addr == ip.ip_src.s_addr)) {
1518 		PIPEX_DBG((NULL, LOG_DEBUG,
1519 		    "<%s> the source address of the session is not matched",
1520 		    __func__));
1521 		goto not_ours;
1522 	}
1523 
1524 	return (session);
1525 
1526 not_ours:
1527 	return (NULL);
1528 }
1529 
1530 struct mbuf *
pipex_pptp_input(struct mbuf * m0,struct pipex_session * session)1531 pipex_pptp_input(struct mbuf *m0, struct pipex_session *session)
1532 {
1533 	int hlen, has_seq, has_ack, nseq;
1534 	const char *reason = "";
1535 	u_char *cp, *seqp = NULL, *ackp = NULL;
1536 	uint32_t flags, seq = 0, ack = 0;
1537 	struct ip *ip;
1538 	struct pipex_gre_header *gre;
1539 	struct pipex_pptp_session *pptp_session;
1540 	int rewind = 0;
1541 
1542 	KASSERT(m0->m_pkthdr.len >= PIPEX_IPGRE_HDRLEN);
1543 	pptp_session = &session->proto.pptp;
1544 
1545 	/* get ip header */
1546 	ip = mtod(m0, struct ip *);
1547 	hlen = ip->ip_hl << 2;
1548 
1549 	/* seek gre header */
1550 	gre = PIPEX_SEEK_NEXTHDR(ip, hlen, struct pipex_gre_header *);
1551 	flags = ntohs(gre->flags);
1552 
1553 	/* pullup for seek sequences in header */
1554 	has_seq = (flags & PIPEX_GRE_SFLAG) ? 1 : 0;
1555 	has_ack = (flags & PIPEX_GRE_AFLAG) ? 1 : 0;
1556 	hlen = PIPEX_IPGRE_HDRLEN + 4 * (has_seq + has_ack);
1557 	if (m0->m_len < hlen) {
1558 		m0 = m_pullup(m0, hlen);
1559 		if (m0 == NULL) {
1560 			PIPEX_DBG((session, LOG_DEBUG, "pullup failed."));
1561 			goto drop;
1562 		}
1563 	}
1564 
1565 	/* check sequence */
1566 	cp = PIPEX_SEEK_NEXTHDR(gre, sizeof(struct pipex_gre_header),u_char *);
1567 	if (has_seq) {
1568 		seqp = cp;
1569 		GETLONG(seq, cp);
1570 	}
1571 
1572 	mtx_enter(&session->pxs_mtx);
1573 
1574 	if (has_ack) {
1575 		ackp = cp;
1576 		GETLONG(ack, cp);
1577 		if (ack + 1 == pptp_session->snd_una) {
1578 			/* ack has not changed before */
1579 		} else if (SEQ32_LT(ack, pptp_session->snd_una)) {
1580 			/* OoO ack packets should not be dropped. */
1581 			rewind = 1;
1582 		} else if (SEQ32_GT(ack, pptp_session->snd_nxt)) {
1583 			reason = "ack for unknown sequence";
1584 			goto out_seq;
1585 		} else
1586 			pptp_session->snd_una = ack + 1;
1587 	}
1588 	if (!has_seq) {
1589 		/* ack only packet */
1590 		goto not_ours;
1591 	}
1592 	if (SEQ32_LT(seq, pptp_session->rcv_nxt)) {
1593 		rewind = 1;
1594 		if (SEQ32_LT(seq,
1595 		    pptp_session->rcv_nxt - PIPEX_REWIND_LIMIT)) {
1596 			reason = "out of sequence";
1597 			goto out_seq;
1598 		}
1599 	} else if (SEQ32_GE(seq, pptp_session->rcv_nxt +
1600 	    pptp_session->maxwinsz)) {
1601 		pipex_session_log(session, LOG_DEBUG,
1602 		    "received packet caused window overflow. seq=%u(%u-%u)"
1603 		    "may lost %d packets.", seq, pptp_session->rcv_nxt,
1604 		    pptp_session->rcv_nxt + pptp_session->maxwinsz,
1605 		    (int)SEQ32_SUB(seq, pptp_session->rcv_nxt));
1606 	}
1607 
1608 	seq++;
1609 	nseq = SEQ32_SUB(seq, pptp_session->rcv_nxt);
1610 	if (!rewind) {
1611 		pptp_session->rcv_nxt = seq;
1612 		if (SEQ32_SUB(seq, pptp_session->rcv_acked) >
1613 		    roundup(pptp_session->winsz, 2) / 2) /* Send ack only packet. */
1614 			pipex_pptp_output(NULL, session, 0, 1);
1615 	}
1616 
1617 	/*
1618 	 * The following pipex_common_input() will release `pxs_mtx'
1619 	 * deep within if the packet will be consumed. In the error
1620 	 * path lock will be held all the time. So increment `rcv_gap'
1621 	 * here, and on the error path back it out, no atomicity will
1622 	 * be lost in all cases.
1623 	 */
1624 	if (!rewind)
1625 		session->proto.pptp.rcv_gap += nseq;
1626 	m0 = pipex_common_input(session, m0, hlen, ntohs(gre->len), 1);
1627 	if (m0 == NULL) {
1628 		/*
1629 		 * pipex_common_input() releases lock if the
1630 		 * packet was consumed.
1631 		 */
1632 		return (NULL);
1633 	}
1634 
1635 	if (rewind)
1636 		goto out_seq;
1637 	else {
1638 		/* The packet is not ours, back out `rcv_gap'. */
1639 		session->proto.pptp.rcv_gap -= nseq;
1640 	}
1641 
1642 not_ours:
1643 	seq--;	/* revert original seq value */
1644 
1645 	/*
1646 	 * overwrite sequence numbers to adjust a gap between pipex and
1647 	 * userland.
1648 	 */
1649 	if (seqp != NULL) {
1650 		seq -= pptp_session->rcv_gap;
1651 		PUTLONG(seq, seqp);
1652 	}
1653 	if (ackp != NULL) {
1654 		if (pptp_session->snd_nxt == pptp_session->snd_una) {
1655 			ack -= session->proto.pptp.snd_gap;
1656 			pptp_session->ul_snd_una = ack;
1657 		} else {
1658 			/*
1659 			 * There are sending packets they are not acked.
1660 			 * In this situation, (ack - snd_gap) may points
1661 			 * before sending window of userland.  So we don't
1662 			 * update the ack number.
1663 			 */
1664 			ack = pptp_session->ul_snd_una;
1665 		}
1666 		PUTLONG(ack, ackp);
1667 	}
1668 
1669 	mtx_leave(&session->pxs_mtx);
1670 
1671 	return (m0);
1672 out_seq:
1673 	pipex_session_log(session, LOG_DEBUG,
1674 	    "Received bad data packet: %s: seq=%u(%u-%u) ack=%u(%u-%u)",
1675 	    reason, seq, pptp_session->rcv_nxt,
1676 	    pptp_session->rcv_nxt + pptp_session->maxwinsz,
1677 	    ack, pptp_session->snd_una,
1678 	    pptp_session->snd_nxt);
1679 	mtx_leave(&session->pxs_mtx);
1680 
1681 	/* FALLTHROUGH */
1682 drop:
1683 	m_freem(m0);
1684 	counters_inc(session->stat_counters, pxc_ierrors);
1685 
1686 	return (NULL);
1687 }
1688 
1689 struct pipex_session *
pipex_pptp_userland_lookup_session_ipv4(struct mbuf * m0,struct in_addr dst)1690 pipex_pptp_userland_lookup_session_ipv4(struct mbuf *m0, struct in_addr dst)
1691 {
1692 	struct sockaddr_in sin;
1693 
1694 	memset(&sin, 0, sizeof(sin));
1695 	sin.sin_len = sizeof(sin);
1696 	sin.sin_family = AF_INET;
1697 	sin.sin_addr = dst;
1698 
1699 	return pipex_pptp_userland_lookup_session(m0, sintosa(&sin));
1700 }
1701 
1702 #ifdef INET6
1703 struct pipex_session *
pipex_pptp_userland_lookup_session_ipv6(struct mbuf * m0,struct in6_addr dst)1704 pipex_pptp_userland_lookup_session_ipv6(struct mbuf *m0, struct in6_addr dst)
1705 {
1706 	struct sockaddr_in6 sin6;
1707 
1708 	memset(&sin6, 0, sizeof(sin6));
1709 	sin6.sin6_len = sizeof(sin6);
1710 	sin6.sin6_family = AF_INET6;
1711 	in6_recoverscope(&sin6, &dst);
1712 
1713 	return pipex_pptp_userland_lookup_session(m0, sin6tosa(&sin6));
1714 }
1715 #endif
1716 
1717 struct pipex_session *
pipex_pptp_userland_lookup_session(struct mbuf * m0,struct sockaddr * sa)1718 pipex_pptp_userland_lookup_session(struct mbuf *m0, struct sockaddr *sa)
1719 {
1720 	struct pipex_gre_header gre;
1721 	struct pipex_hash_head *list;
1722 	struct pipex_session *session;
1723 	uint16_t id, flags;
1724 
1725 	/* pullup */
1726 	if (m0->m_pkthdr.len < sizeof(gre)) {
1727 		PIPEX_DBG((NULL, LOG_DEBUG,
1728 		    "<%s> packet length is too short", __func__));
1729 		return (NULL);
1730 	}
1731 
1732 	/* get flags */
1733 	m_copydata(m0, 0, sizeof(struct pipex_gre_header), &gre);
1734 	flags = ntohs(gre.flags);
1735 
1736 	/* gre version must be '1' */
1737 	if ((flags & PIPEX_GRE_VERMASK) != PIPEX_GRE_VER) {
1738 		PIPEX_DBG((NULL, LOG_DEBUG,
1739 		    "<%s> gre header wrong version.", __func__));
1740 		return (NULL);
1741 	}
1742 
1743 	/* gre keys must be present */
1744 	if ((flags & PIPEX_GRE_KFLAG) == 0) {
1745 		PIPEX_DBG((NULL, LOG_DEBUG,
1746 		    "<%s> gre header has no keys.", __func__));
1747 		return (NULL);
1748 	}
1749 
1750 	/* lookup pipex session table */
1751 	id = ntohs(gre.call_id);
1752 
1753 	mtx_enter(&pipex_list_mtx);
1754 
1755 	list = PIPEX_PEER_ADDR_HASHTABLE(pipex_sockaddr_hash_key(sa));
1756 	LIST_FOREACH(session, list, peer_addr_chain) {
1757 		if (pipex_sockaddr_compar_addr(&session->peer.sa, sa) != 0)
1758 			continue;
1759 		if (session->peer_session_id == id)
1760 			break;
1761 	}
1762 
1763 	if (session != NULL)
1764 		refcnt_take(&session->pxs_refcnt);
1765 
1766 	mtx_leave(&pipex_list_mtx);
1767 
1768 #ifdef PIPEX_DEBUG
1769 	if (session == NULL) {
1770 		PIPEX_DBG((NULL, LOG_DEBUG,
1771 		    "<%s> session not found (,call_id=%d)",
1772 		    __func__, (int)gre.call_id));
1773 	}
1774 #endif
1775 	return (session);
1776 }
1777 
1778 /*
1779  * pipex_pptp_userland_output
1780  */
1781 struct mbuf *
pipex_pptp_userland_output(struct mbuf * m0,struct pipex_session * session)1782 pipex_pptp_userland_output(struct mbuf *m0, struct pipex_session *session)
1783 {
1784 	int len;
1785 	struct pipex_gre_header *gre, gre0;
1786 	uint16_t flags;
1787 	u_char *cp, *cp0;
1788 	uint32_t val32;
1789 
1790 	len = sizeof(struct pipex_gre_header);
1791 	m_copydata(m0, 0, len, &gre0);
1792 	gre = &gre0;
1793 	flags = ntohs(gre->flags);
1794 	if ((flags & PIPEX_GRE_SFLAG) != 0)
1795 		len += 4;
1796 	if ((flags & PIPEX_GRE_AFLAG) != 0)
1797 		len += 4;
1798 
1799 	/* check length */
1800 	PIPEX_PULLUP(m0, len);
1801 	if (m0 == NULL) {
1802 		PIPEX_DBG((session, LOG_DEBUG, "gre header is too short."));
1803 		return (NULL);
1804 	}
1805 
1806 	gre = mtod(m0, struct pipex_gre_header *);
1807 	cp = PIPEX_SEEK_NEXTHDR(gre, sizeof(struct pipex_gre_header), u_char *);
1808 
1809 	mtx_enter(&session->pxs_mtx);
1810 
1811 	/*
1812 	 * overwrite sequence numbers to adjust a gap between pipex and
1813 	 * userland.
1814 	 */
1815 	if ((flags & PIPEX_GRE_SFLAG) != 0) {
1816 		cp0 = cp;
1817 		GETLONG(val32, cp);
1818 		val32 += session->proto.pptp.snd_gap;
1819 		PUTLONG(val32, cp0);
1820 		session->proto.pptp.snd_nxt++;
1821 	}
1822 	if ((flags & PIPEX_GRE_AFLAG) != 0) {
1823 		cp0 = cp;
1824 		GETLONG(val32, cp);
1825 		val32 += session->proto.pptp.rcv_gap;
1826 		PUTLONG(val32, cp0);
1827 		if (SEQ32_GT(val32, session->proto.pptp.rcv_acked))
1828 			session->proto.pptp.rcv_acked = val32;
1829 	}
1830 
1831 	mtx_leave(&session->pxs_mtx);
1832 
1833 	return (m0);
1834 }
1835 #endif /* PIPEX_PPTP */
1836 
1837 #ifdef PIPEX_L2TP
1838 /***********************************************************************
1839  * L2TP support
1840  ***********************************************************************/
1841 void
pipex_l2tp_output(struct mbuf * m0,struct pipex_session * session)1842 pipex_l2tp_output(struct mbuf *m0, struct pipex_session *session)
1843 {
1844 	int hlen, plen, datalen;
1845 	struct pipex_l2tp_header *l2tp = NULL;
1846 	struct pipex_l2tp_seq_header *seq = NULL;
1847 	struct udphdr *udp;
1848 	struct ip *ip;
1849 #ifdef INET6
1850 	struct ip6_hdr *ip6;
1851 #endif
1852 	struct m_tag *mtag;
1853 
1854 	hlen = sizeof(struct pipex_l2tp_header) +
1855 	    ((pipex_session_is_l2tp_data_sequencing_on(session))
1856 		    ? sizeof(struct pipex_l2tp_seq_header) : 0) +
1857 	    sizeof(struct udphdr) +
1858 #ifdef INET6
1859 	    ((session->peer.sin6.sin6_family == AF_INET6)
1860 		    ? sizeof(struct ip6_hdr) : sizeof(struct ip));
1861 #else
1862 	    sizeof(struct ip);
1863 #endif
1864 
1865 	datalen = 0;
1866 	if (m0 != NULL) {
1867 		datalen = m0->m_pkthdr.len;
1868 		M_PREPEND(m0, hlen, M_NOWAIT);
1869 		if (m0 == NULL)
1870 			goto drop;
1871 	} else {
1872 		MGETHDR(m0, M_DONTWAIT, MT_DATA);
1873 		if (m0 == NULL)
1874 			goto drop;
1875 		KASSERT(hlen <= MHLEN);
1876 		m0->m_pkthdr.len = m0->m_len = hlen;
1877 	}
1878 
1879 #ifdef INET6
1880 	hlen = (session->peer.sin6.sin6_family == AF_INET6)
1881 	    ? sizeof(struct ip6_hdr) : sizeof(struct ip);
1882 #else
1883 	hlen = sizeof(struct ip);
1884 #endif
1885 	plen = datalen + sizeof(struct pipex_l2tp_header) +
1886 	    ((pipex_session_is_l2tp_data_sequencing_on(session))
1887 		    ? sizeof(struct pipex_l2tp_seq_header) : 0);
1888 
1889 	l2tp = (struct pipex_l2tp_header *)
1890 	    (mtod(m0, caddr_t) + hlen + sizeof(struct udphdr));
1891 	l2tp->flagsver = PIPEX_L2TP_VER | PIPEX_L2TP_FLAG_LENGTH;
1892 	l2tp->length = htons(plen);
1893 	l2tp->tunnel_id = htons(session->proto.l2tp.peer_tunnel_id);
1894 	l2tp->session_id = htons(session->peer_session_id);
1895 	if (pipex_session_is_l2tp_data_sequencing_on(session)) {
1896 		seq = (struct pipex_l2tp_seq_header *)(l2tp + 1);
1897 		l2tp->flagsver |= PIPEX_L2TP_FLAG_SEQUENCE;
1898 
1899 		mtx_enter(&session->pxs_mtx);
1900 		seq->ns = htons(session->proto.l2tp.ns_nxt);
1901 		session->proto.l2tp.ns_nxt++;
1902 		session->proto.l2tp.ns_gap++;
1903 		session->proto.l2tp.nr_acked = session->proto.l2tp.nr_nxt - 1;
1904 		seq->nr = htons(session->proto.l2tp.nr_acked);
1905 		mtx_leave(&session->pxs_mtx);
1906 	}
1907 	l2tp->flagsver = htons(l2tp->flagsver);
1908 
1909 	plen += sizeof(struct udphdr);
1910 	udp = (struct udphdr *)(mtod(m0, caddr_t) + hlen);
1911 	udp->uh_sport = session->local.sin6.sin6_port;
1912 	udp->uh_dport = session->peer.sin6.sin6_port;
1913 	udp->uh_ulen = htons(plen);
1914 	udp->uh_sum = 0;
1915 
1916 	m0->m_pkthdr.csum_flags |= M_UDP_CSUM_OUT;
1917 	m0->m_pkthdr.ph_ifidx = session->ifindex;
1918 #if NPF > 0
1919 	pf_pkt_addr_changed(m0);
1920 #endif
1921 	switch (session->peer.sin6.sin6_family) {
1922 	case AF_INET:
1923 		ip = mtod(m0, struct ip *);
1924 		ip->ip_p = IPPROTO_UDP;
1925 		ip->ip_src = session->local.sin4.sin_addr;
1926 		ip->ip_dst = session->peer.sin4.sin_addr;
1927 		ip->ip_len = htons(hlen + plen);
1928 		ip->ip_ttl = MAXTTL;
1929 		ip->ip_tos = 0;
1930 		ip->ip_off = 0;
1931 
1932 		mtx_enter(&session->pxs_mtx);
1933 		if (session->proto.l2tp.ipsecflowinfo > 0) {
1934 			if ((mtag = m_tag_get(PACKET_TAG_IPSEC_FLOWINFO,
1935 			    sizeof(u_int32_t), M_NOWAIT)) == NULL) {
1936 				mtx_leave(&session->pxs_mtx);
1937 				goto drop;
1938 			}
1939 
1940 			*(u_int32_t *)(mtag + 1) =
1941 			    session->proto.l2tp.ipsecflowinfo;
1942 			m_tag_prepend(m0, mtag);
1943 		}
1944 		mtx_leave(&session->pxs_mtx);
1945 
1946 		ip_send(m0);
1947 		break;
1948 #ifdef INET6
1949 	case AF_INET6:
1950 		ip6 = mtod(m0, struct ip6_hdr *);
1951 
1952 		ip6->ip6_flow = 0;
1953 		ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
1954 		ip6->ip6_vfc |= IPV6_VERSION;
1955 		ip6->ip6_nxt = IPPROTO_UDP;
1956 		ip6->ip6_src = session->local.sin6.sin6_addr;
1957 		in6_embedscope(&ip6->ip6_dst, &session->peer.sin6, NULL, NULL);
1958 		/* ip6->ip6_plen will be filled in ip6_output. */
1959 
1960 		ip6_send(m0);
1961 		break;
1962 #endif
1963 	}
1964 	udpstat_inc(udps_opackets);
1965 
1966 	if (datalen > 0) {	/* network layer only */
1967 		/* countup statistics */
1968 		counters_pkt(session->stat_counters, pxc_opackets,
1969 		    pxc_obytes, datalen);
1970 	}
1971 
1972 	return;
1973 drop:
1974 	m_freem(m0);
1975 	counters_inc(session->stat_counters, pxc_oerrors);
1976 }
1977 
1978 struct pipex_session *
pipex_l2tp_lookup_session(struct mbuf * m0,int off,struct sockaddr * sasrc)1979 pipex_l2tp_lookup_session(struct mbuf *m0, int off, struct sockaddr *sasrc)
1980 {
1981 	struct pipex_session *session;
1982 	uint16_t flags, session_id, ver;
1983 	u_char *cp, buf[PIPEX_L2TP_MINLEN];
1984 	int srcmatch = 0;
1985 
1986 	if (m0->m_pkthdr.len < off + PIPEX_L2TP_MINLEN) {
1987 		PIPEX_DBG((NULL, LOG_DEBUG,
1988 		    "<%s> packet length is too short", __func__));
1989 		goto not_ours;
1990 	}
1991 
1992 	/* get first 16bits of L2TP */
1993 	m_copydata(m0, off, sizeof(buf), buf);
1994 	cp = buf;
1995 	GETSHORT(flags, cp);
1996 	ver = flags & PIPEX_L2TP_VER_MASK;
1997 
1998 	/* l2tp version must be '2' */
1999 	if (ver != PIPEX_L2TP_VER) {
2000 		PIPEX_DBG((NULL, LOG_DEBUG,
2001 		    "<%s> l2tp header wrong version %u.", __func__, ver));
2002 		goto not_ours;
2003 	}
2004 	if ((flags & PIPEX_L2TP_FLAG_TYPE) != 0)
2005 		goto not_ours;
2006 
2007 	if (flags & PIPEX_L2TP_FLAG_LENGTH)
2008 		cp += 2;			/* skip length field */
2009 	cp += 2;				/* skip tunnel-id field */
2010 	GETSHORT(session_id, cp);		/* get session-id field */
2011 
2012 	/* lookup pipex session table */
2013 	session = pipex_lookup_by_session_id(PIPEX_PROTO_L2TP, session_id);
2014 	if (session == NULL) {
2015 		PIPEX_DBG((NULL, LOG_DEBUG,
2016 		    "<%s> session not found (id=%d)", __func__, session_id));
2017 		goto not_ours;
2018 	}
2019 	switch (sasrc->sa_family) {
2020 	case AF_INET:
2021 		if (session->peer.sa.sa_family == AF_INET &&
2022 		    session->peer.sin4.sin_addr.s_addr ==
2023 		    ((struct sockaddr_in *)sasrc)->sin_addr.s_addr)
2024 			srcmatch = 1;
2025 		break;
2026 #ifdef INET6
2027 	case AF_INET6:
2028 		if (session->peer.sa.sa_family == AF_INET6 &&
2029 		    IN6_ARE_ADDR_EQUAL(&session->peer.sin6.sin6_addr,
2030 		    &((struct sockaddr_in6 *)sasrc)->sin6_addr))
2031 			srcmatch = 1;
2032 		break;
2033 #endif
2034 	}
2035 	if (!srcmatch) {
2036 		PIPEX_DBG((NULL, LOG_DEBUG,
2037 		    "<%s> the source address of the session is not matched",
2038 		    __func__));
2039 		goto not_ours;
2040 	}
2041 
2042 	return (session);
2043 
2044 not_ours:
2045 	return (NULL);
2046 }
2047 
2048 struct mbuf *
pipex_l2tp_input(struct mbuf * m0,int off0,struct pipex_session * session,uint32_t ipsecflowinfo)2049 pipex_l2tp_input(struct mbuf *m0, int off0, struct pipex_session *session,
2050     uint32_t ipsecflowinfo)
2051 {
2052 	struct pipex_l2tp_session *l2tp_session;
2053 	int length = 0, offset = 0, hlen, nseq;
2054 	u_char *cp, *nsp = NULL, *nrp = NULL;
2055 	uint16_t flags, ns = 0, nr = 0;
2056 	int rewind = 0;
2057 
2058 	mtx_enter(&session->pxs_mtx);
2059 
2060 	l2tp_session = &session->proto.l2tp;
2061 	if (l2tp_session->ipsecflowinfo > 0 &&
2062 	    l2tp_session->ipsecflowinfo != ipsecflowinfo) {
2063 		pipex_session_log(session, LOG_DEBUG,
2064 		    "received message is %s",
2065 		    (ipsecflowinfo != 0)? "from invalid ipsec flow" :
2066 		    "without ipsec");
2067 		goto drop;
2068 	}
2069 
2070 	m_copydata(m0, off0, sizeof(flags), &flags);
2071 
2072 	flags = ntohs(flags) & PIPEX_L2TP_FLAG_MASK;
2073 	KASSERT((flags & PIPEX_L2TP_FLAG_TYPE) == 0);
2074 
2075 	hlen = 2;				/* flags and version fields */
2076 	if (flags & PIPEX_L2TP_FLAG_LENGTH)	/* length */
2077 		hlen += 2;
2078 	hlen += 4;				/* tunnel-id and session-id */
2079 	if (flags & PIPEX_L2TP_FLAG_SEQUENCE)	/* ns and nr */
2080 		hlen += 4;
2081 	if (flags & PIPEX_L2TP_FLAG_OFFSET)	/* offset */
2082 		hlen += 2;
2083 
2084 	PIPEX_PULLUP(m0, off0 + hlen);
2085 	if (m0  == NULL)
2086 		goto drop;
2087 
2088 	cp = mtod(m0, u_char *) + off0;
2089 	cp += 2;	/* flags and version */
2090 	if (flags & PIPEX_L2TP_FLAG_LENGTH)
2091 		GETSHORT(length, cp);
2092 	else
2093 		length = m0->m_pkthdr.len - off0;
2094 	cp += 4;	/* skip tunnel-id and session-id field */
2095 
2096 	/* pullup for seek sequences in header */
2097 	nseq = 0;
2098 	if (flags & PIPEX_L2TP_FLAG_SEQUENCE) {
2099 		nsp = cp;
2100 		GETSHORT(ns, cp);
2101 		nrp = cp;
2102 		GETSHORT(nr, cp);
2103 
2104 		nr++;
2105 		if (SEQ16_GT(nr, l2tp_session->ns_una) &&
2106 		    SEQ16_LE(nr, l2tp_session->ns_nxt))
2107 			/* update 'ns_una' only if the ns is in valid range */
2108 			l2tp_session->ns_una = nr;
2109 		if (SEQ16_LT(ns, l2tp_session->nr_nxt)) {
2110 			rewind = 1;
2111 			if (SEQ16_LT(ns,
2112 			    l2tp_session->nr_nxt - PIPEX_REWIND_LIMIT))
2113 				goto out_seq;
2114 		}
2115 
2116 		ns++;
2117 		nseq = SEQ16_SUB(ns, l2tp_session->nr_nxt);
2118 		if (!rewind)
2119 			l2tp_session->nr_nxt = ns;
2120 	}
2121 	if (flags & PIPEX_L2TP_FLAG_OFFSET)
2122 		GETSHORT(offset, cp);
2123 
2124 	length -= hlen + offset;
2125 	hlen += off0 + offset;
2126 
2127 	/*
2128 	 * The following pipex_common_input() will release `pxs_mtx'
2129 	 * deep within if the packet will be consumed. In the error
2130 	 * path lock will be held all the time. So increment `nr_gap'
2131 	 * here, and on the error path back it out, no atomicity will
2132 	 * be lost in all cases.
2133 	 */
2134 	if (!rewind)
2135 		session->proto.l2tp.nr_gap += nseq;
2136 	m0 = pipex_common_input(session, m0, hlen, length, 1);
2137 	if (m0 == NULL) {
2138 		/*
2139 		 * pipex_common_input() releases lock if the
2140 		 * packet was consumed.
2141 		 */
2142 		return (NULL);
2143 	}
2144 
2145 	if (rewind)
2146 		goto out_seq;
2147 	else {
2148 		/* The packet is not ours, backout `nr_gap'. */
2149 		session->proto.l2tp.nr_gap -= nseq;
2150 	}
2151 
2152 	/*
2153 	 * overwrite sequence numbers to adjust a gap between pipex and
2154 	 * userland.
2155 	 */
2156 	if (flags & PIPEX_L2TP_FLAG_SEQUENCE) {
2157 		--ns; --nr;	/* revert original values */
2158 		ns -= l2tp_session->nr_gap;
2159 		PUTSHORT(ns, nsp);
2160 
2161 		if (l2tp_session->ns_nxt == l2tp_session->ns_una) {
2162 			nr -= l2tp_session->ns_gap;
2163 			l2tp_session->ul_ns_una = nr;
2164 		} else {
2165 			/*
2166 			 * There are sending packets they are not acked.
2167 			 * In this situation, (ack - snd_gap) may points
2168 			 * before sending window of userland.  So we don't
2169 			 * update the ack number.
2170 			 */
2171 			nr = l2tp_session->ul_ns_una;
2172 		}
2173 		PUTSHORT(nr, nrp);
2174 	}
2175 
2176 	mtx_leave(&session->pxs_mtx);
2177 
2178 	return (m0);
2179 out_seq:
2180 	pipex_session_log(session, LOG_DEBUG,
2181 	    "Received bad data packet: out of sequence: seq=%u(%u-) "
2182 	    "ack=%u(%u-%u)", ns, l2tp_session->nr_nxt, nr, l2tp_session->ns_una,
2183 	    l2tp_session->ns_nxt);
2184 	/* FALLTHROUGH */
2185 drop:
2186 	mtx_leave(&session->pxs_mtx);
2187 
2188 	m_freem(m0);
2189 	counters_inc(session->stat_counters, pxc_ierrors);
2190 
2191 	return (NULL);
2192 }
2193 
2194 struct pipex_session *
pipex_l2tp_userland_lookup_session_ipv4(struct mbuf * m0,struct in_addr dst)2195 pipex_l2tp_userland_lookup_session_ipv4(struct mbuf *m0, struct in_addr dst)
2196 {
2197 	struct sockaddr_in sin;
2198 
2199 	memset(&sin, 0, sizeof(sin));
2200 	sin.sin_len = sizeof(sin);
2201 	sin.sin_family = AF_INET;
2202 	sin.sin_addr = dst;
2203 
2204 	return pipex_l2tp_userland_lookup_session(m0, sintosa(&sin));
2205 }
2206 
2207 #ifdef INET6
2208 struct pipex_session *
pipex_l2tp_userland_lookup_session_ipv6(struct mbuf * m0,struct in6_addr dst)2209 pipex_l2tp_userland_lookup_session_ipv6(struct mbuf *m0, struct in6_addr dst)
2210 {
2211 	struct sockaddr_in6 sin6;
2212 
2213 	memset(&sin6, 0, sizeof(sin6));
2214 	sin6.sin6_len = sizeof(sin6);
2215 	sin6.sin6_family = AF_INET6;
2216 	in6_recoverscope(&sin6, &dst);
2217 
2218 	return pipex_l2tp_userland_lookup_session(m0, sin6tosa(&sin6));
2219 }
2220 #endif
2221 
2222 struct pipex_session *
pipex_l2tp_userland_lookup_session(struct mbuf * m0,struct sockaddr * sa)2223 pipex_l2tp_userland_lookup_session(struct mbuf *m0, struct sockaddr *sa)
2224 {
2225 	struct pipex_l2tp_header l2tp;
2226 	struct pipex_hash_head *list;
2227 	struct pipex_session *session;
2228 	uint16_t session_id, tunnel_id, flags;
2229 
2230 	if (sa->sa_family != AF_INET && sa->sa_family != AF_INET6)
2231 		return (NULL);
2232 
2233 	/* pullup */
2234 	if (m0->m_pkthdr.len < sizeof(l2tp)) {
2235 		PIPEX_DBG((NULL, LOG_DEBUG,
2236 		    "<%s> packet length is too short", __func__));
2237 		return (NULL);
2238 	}
2239 
2240 	/* get flags */
2241 	m_copydata(m0, 0, sizeof(l2tp), &l2tp);
2242 	flags = ntohs(l2tp.flagsver);
2243 
2244 	/* l2tp version must be '2' */
2245 	if ((flags & PIPEX_L2TP_VER_MASK) != PIPEX_L2TP_VER) {
2246 		PIPEX_DBG((NULL, LOG_DEBUG,
2247 		    "<%s> l2tp header wrong version.", __func__));
2248 		return (NULL);
2249 	}
2250 	/* We need L2TP data messages only */
2251 	if ((flags & PIPEX_L2TP_FLAG_TYPE) != 0)
2252 		return (NULL);
2253 	/* No need to hook packets that don't have the sequence field */
2254 	if ((flags & PIPEX_L2TP_FLAG_SEQUENCE) == 0)
2255 		return (NULL);
2256 
2257 	session_id = ntohs(l2tp.session_id);
2258 	tunnel_id = ntohs(l2tp.tunnel_id);
2259 
2260 	mtx_enter(&pipex_list_mtx);
2261 
2262 	list = PIPEX_PEER_ADDR_HASHTABLE(pipex_sockaddr_hash_key(sa));
2263 	LIST_FOREACH(session, list, peer_addr_chain) {
2264 		if (pipex_sockaddr_compar_addr(&session->peer.sa, sa) != 0)
2265 			continue;
2266 		if (session->proto.l2tp.peer_tunnel_id != tunnel_id)
2267 			continue;
2268 		if (session->peer_session_id == session_id)
2269 			break;
2270 	}
2271 
2272 	if (session != NULL)
2273 		refcnt_take(&session->pxs_refcnt);
2274 
2275 	mtx_leave(&pipex_list_mtx);
2276 
2277 #ifdef PIPEX_DEBUG
2278 	if (session == NULL) {
2279 		PIPEX_DBG((NULL, LOG_DEBUG, "<%s> session not found "
2280 		    "(tunnel_id=%d, session_id=%d)", __func__,
2281 		    tunnel_id, session_id));
2282 	}
2283 #endif
2284 
2285 	return (session);
2286 }
2287 
2288 struct mbuf *
pipex_l2tp_userland_output(struct mbuf * m0,struct pipex_session * session)2289 pipex_l2tp_userland_output(struct mbuf *m0, struct pipex_session *session)
2290 {
2291 	struct pipex_l2tp_header *l2tp;
2292 	struct pipex_l2tp_seq_header *seq;
2293 	uint16_t ns, nr;
2294 
2295 	/* check length */
2296 	PIPEX_PULLUP(m0, sizeof(struct pipex_l2tp_header) +
2297 	    sizeof(struct pipex_l2tp_seq_header));
2298 	if (m0 == NULL)
2299 		return (NULL);
2300 
2301 	l2tp = mtod(m0, struct pipex_l2tp_header *);
2302 	KASSERT(ntohs(l2tp->flagsver) & PIPEX_L2TP_FLAG_SEQUENCE);
2303 
2304 	/*
2305 	 * overwrite sequence numbers to adjust a gap between pipex and
2306 	 * userland.
2307 	 */
2308 	seq = (struct pipex_l2tp_seq_header *)(l2tp + 1);
2309 	ns = ntohs(seq->ns);
2310 	nr = ntohs(seq->nr);
2311 
2312 	mtx_enter(&session->pxs_mtx);
2313 
2314 	ns += session->proto.l2tp.ns_gap;
2315 	seq->ns = htons(ns);
2316 	session->proto.l2tp.ns_nxt++;
2317 
2318 	nr += session->proto.l2tp.nr_gap;
2319 	seq->nr = htons(nr);
2320 	if (SEQ16_GT(nr, session->proto.l2tp.nr_acked))
2321 		session->proto.l2tp.nr_acked = nr;
2322 
2323 	mtx_leave(&session->pxs_mtx);
2324 
2325 	return (m0);
2326 }
2327 #endif /* PIPEX_L2TP */
2328 
2329 #ifdef PIPEX_MPPE
2330 /**********************************************************************
2331  * MPPE
2332  ***********************************************************************/
2333 #define	PIPEX_COHERENCY_CNT_MASK		0x0fff
2334 
2335 static inline int
pipex_mppe_setkey(struct pipex_mppe * mppe)2336 pipex_mppe_setkey(struct pipex_mppe *mppe)
2337 {
2338 	rc4_keysetup(&mppe->rc4ctx, mppe->session_key, mppe->keylen);
2339 
2340 	return (0);
2341 }
2342 
2343 static inline int
pipex_mppe_setoldkey(struct pipex_mppe * mppe,uint16_t coher_cnt)2344 pipex_mppe_setoldkey(struct pipex_mppe *mppe, uint16_t coher_cnt)
2345 {
2346 	KASSERT(mppe->old_session_keys != NULL);
2347 
2348 	rc4_keysetup(&mppe->rc4ctx,
2349 	    mppe->old_session_keys[coher_cnt & PIPEX_MPPE_OLDKEYMASK],
2350 	    mppe->keylen);
2351 
2352 	return (0);
2353 }
2354 
2355 static inline void
pipex_mppe_crypt(struct pipex_mppe * mppe,int len,u_char * indata,u_char * outdata)2356 pipex_mppe_crypt(struct pipex_mppe *mppe, int len, u_char *indata,
2357     u_char *outdata)
2358 {
2359 	rc4_crypt(&mppe->rc4ctx, indata, outdata, len);
2360 }
2361 
2362 void
pipex_mppe_init(struct pipex_mppe * mppe,int stateless,int keylenbits,u_char * master_key,int has_oldkey)2363 pipex_mppe_init(struct pipex_mppe *mppe, int stateless, int keylenbits,
2364     u_char *master_key, int has_oldkey)
2365 {
2366 	memset(mppe, 0, sizeof(struct pipex_mppe));
2367 	mtx_init(&mppe->pxm_mtx, IPL_SOFTNET);
2368 	if (stateless)
2369 		mppe->flags |= PIPEX_MPPE_STATELESS;
2370 	if (has_oldkey)
2371 		mppe->old_session_keys =
2372 		    pool_get(&mppe_key_pool, PR_WAITOK);
2373 	else
2374 		mppe->old_session_keys = NULL;
2375 	memcpy(mppe->master_key, master_key, sizeof(mppe->master_key));
2376 
2377 	mppe->keylenbits = keylenbits;
2378 	switch (keylenbits) {
2379 	case 40:
2380 	case 56:
2381 		mppe->keylen = 8;
2382 		break;
2383 	case 128:
2384 		mppe->keylen = 16;
2385 		break;
2386 	}
2387 
2388 	GetNewKeyFromSHA(mppe->master_key, mppe->master_key, mppe->keylen,
2389 	    mppe->session_key);
2390 	pipex_mppe_reduce_key(mppe);
2391 	pipex_mppe_setkey(mppe);
2392 }
2393 
2394 void
pipex_session_init_mppe_recv(struct pipex_session * session,int stateless,int keylenbits,u_char * master_key)2395 pipex_session_init_mppe_recv(struct pipex_session *session, int stateless,
2396     int keylenbits, u_char *master_key)
2397 {
2398 	pipex_mppe_init(&session->mppe_recv, stateless, keylenbits,
2399 	    master_key, stateless);
2400 	session->ppp_flags |= PIPEX_PPP_MPPE_ACCEPTED;
2401 }
2402 
2403 void
pipex_session_init_mppe_send(struct pipex_session * session,int stateless,int keylenbits,u_char * master_key)2404 pipex_session_init_mppe_send(struct pipex_session *session, int stateless,
2405     int keylenbits, u_char *master_key)
2406 {
2407 	pipex_mppe_init(&session->mppe_send, stateless, keylenbits,
2408 	    master_key, 0);
2409 	session->ppp_flags |= PIPEX_PPP_MPPE_ENABLED;
2410 }
2411 
2412 #include <crypto/sha1.h>
2413 
2414 static u_char SHAPad1[] = {
2415 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2416 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2417 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2418 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2419 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2420 }, SHAPad2[] = {
2421 	0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
2422 	0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
2423 	0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
2424 	0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
2425 	0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
2426 };
2427 
2428 void
GetNewKeyFromSHA(u_char * StartKey,u_char * SessionKey,int SessionKeyLength,u_char * InterimKey)2429 GetNewKeyFromSHA(u_char *StartKey, u_char *SessionKey, int SessionKeyLength,
2430     u_char *InterimKey)
2431 {
2432 	u_char Digest[20];
2433 	SHA1_CTX Context;
2434 
2435 	SHA1Init(&Context);
2436 	SHA1Update(&Context, StartKey, SessionKeyLength);
2437 	SHA1Update(&Context, SHAPad1, 40);
2438 	SHA1Update(&Context, SessionKey, SessionKeyLength);
2439 	SHA1Update(&Context, SHAPad2, 40);
2440 	SHA1Final(Digest, &Context);
2441 
2442 	memcpy(InterimKey, Digest, SessionKeyLength);
2443 }
2444 
2445 void
pipex_mppe_reduce_key(struct pipex_mppe * mppe)2446 pipex_mppe_reduce_key(struct pipex_mppe *mppe)
2447 {
2448 	switch (mppe->keylenbits) {
2449 	case 40:
2450 		mppe->session_key[0] = 0xd1;
2451 		mppe->session_key[1] = 0x26;
2452 		mppe->session_key[2] = 0x9e;
2453 		break;
2454 	case 56:
2455 		mppe->session_key[0] = 0xd1;
2456 		break;
2457 	}
2458 }
2459 
2460 void
mppe_key_change(struct pipex_mppe * mppe)2461 mppe_key_change(struct pipex_mppe *mppe)
2462 {
2463 	u_char interim[16];
2464 	struct rc4_ctx keychg;
2465 
2466 	memset(&keychg, 0, sizeof(keychg));
2467 
2468 	GetNewKeyFromSHA(mppe->master_key, mppe->session_key, mppe->keylen,
2469 	    interim);
2470 
2471 	rc4_keysetup(&keychg, interim, mppe->keylen);
2472 	rc4_crypt(&keychg, interim, mppe->session_key, mppe->keylen);
2473 
2474 	pipex_mppe_reduce_key(mppe);
2475 
2476 	if (mppe->old_session_keys) {
2477 		int idx = mppe->coher_cnt & PIPEX_MPPE_OLDKEYMASK;
2478 		memcpy(mppe->old_session_keys[idx],
2479 		    mppe->session_key, PIPEX_MPPE_KEYLEN);
2480 	}
2481 }
2482 
2483 struct mbuf *
pipex_mppe_input(struct mbuf * m0,struct pipex_session * session)2484 pipex_mppe_input(struct mbuf *m0, struct pipex_session *session)
2485 {
2486 	int pktloss, encrypt, flushed, m, n, len;
2487 	struct pipex_mppe *mppe;
2488 	uint16_t coher_cnt;
2489 	struct mbuf *m1;
2490 	u_char *cp;
2491 	int rewind = 0;
2492 
2493 	/* pullup */
2494 	PIPEX_PULLUP(m0, sizeof(coher_cnt));
2495 	if (m0 == NULL)
2496 		goto drop;
2497 
2498 	mppe = &session->mppe_recv;
2499 	/* get header information */
2500 	cp = mtod(m0, u_char *);
2501 	GETSHORT(coher_cnt, cp);
2502 	flushed = ((coher_cnt & 0x8000) != 0) ? 1 : 0;
2503 	encrypt = ((coher_cnt & 0x1000) != 0) ? 1 : 0;
2504 	coher_cnt &= PIPEX_COHERENCY_CNT_MASK;
2505 	pktloss = 0;
2506 
2507 	mtx_enter(&mppe->pxm_mtx);
2508 
2509 	PIPEX_MPPE_DBG((session, LOG_DEBUG, "in coher_cnt=%03x %s%s",
2510 	    mppe->coher_cnt, (flushed) ? "[flushed]" : "",
2511 	    (encrypt) ? "[encrypt]" : ""));
2512 
2513 	if (encrypt == 0) {
2514 		mtx_leave(&mppe->pxm_mtx);
2515 		pipex_session_log(session, LOG_DEBUG,
2516 		    "Received unexpected MPPE packet.(no ecrypt)");
2517 		goto drop;
2518 	}
2519 
2520 	/* adjust mbuf */
2521 	m_adj(m0, sizeof(coher_cnt));
2522 
2523 	/*
2524 	 * L2TP data session may be used without sequencing, PPP frames may
2525 	 * arrive in disorder.  The 'coherency counter' of MPPE detects such
2526 	 * situations, but we cannot distinguish between 'disorder' and
2527 	 * 'packet loss' exactly.
2528 	 *
2529 	 * When 'coherency counter' detects lost packets greater than
2530 	 * (4096 - 256), we treat as 'disorder' otherwise treat as
2531 	 * 'packet loss'.
2532 	 */
2533     {
2534 	int coher_cnt0;
2535 
2536 	coher_cnt0 = coher_cnt;
2537 	if (coher_cnt < mppe->coher_cnt)
2538 		coher_cnt0 += 0x1000;
2539 	if (coher_cnt0 - mppe->coher_cnt > 0x0f00) {
2540 		if ((mppe->flags & PIPEX_MPPE_STATELESS) == 0 ||
2541 		    coher_cnt0 - mppe->coher_cnt
2542 		    <= 0x1000 - PIPEX_MPPE_NOLDKEY) {
2543 			pipex_session_log(session, LOG_DEBUG,
2544 			    "Workaround the out-of-sequence PPP framing problem: "
2545 			    "%d => %d", mppe->coher_cnt, coher_cnt);
2546 			mtx_leave(&mppe->pxm_mtx);
2547 			goto drop;
2548 		}
2549 		rewind = 1;
2550 	}
2551     }
2552 
2553 	if ((mppe->flags & PIPEX_MPPE_STATELESS) != 0) {
2554 		if (!rewind) {
2555 			mppe_key_change(mppe);
2556 			while (mppe->coher_cnt != coher_cnt) {
2557 				mppe->coher_cnt++;
2558 				mppe->coher_cnt &= PIPEX_COHERENCY_CNT_MASK;
2559 				mppe_key_change(mppe);
2560 				pktloss++;
2561 			}
2562 		}
2563 		pipex_mppe_setoldkey(mppe, coher_cnt);
2564 	} else {
2565 		if (flushed) {
2566 			if (coher_cnt < mppe->coher_cnt) {
2567 				coher_cnt += 0x1000;
2568 			}
2569 			pktloss += coher_cnt - mppe->coher_cnt;
2570 			m = mppe->coher_cnt / 256;
2571 			n = coher_cnt / 256;
2572 			while (m++ < n)
2573 				mppe_key_change(mppe);
2574 
2575 			coher_cnt &= PIPEX_COHERENCY_CNT_MASK;
2576 			mppe->coher_cnt = coher_cnt;
2577 		} else if (mppe->coher_cnt != coher_cnt) {
2578 			int ccp_id;
2579 
2580 			mtx_leave(&mppe->pxm_mtx);
2581 
2582 			/* Send CCP ResetReq */
2583 			PIPEX_DBG((session, LOG_DEBUG, "CCP SendResetReq"));
2584 
2585 			mtx_enter(&session->pxs_mtx);
2586 			ccp_id = session->ccp_id;
2587 			session->ccp_id++;
2588 			mtx_leave(&session->pxs_mtx);
2589 
2590 			pipex_ccp_output(session, CCP_RESETREQ, ccp_id);
2591 			goto drop;
2592 		}
2593 		if ((coher_cnt & 0xff) == 0xff) {
2594 			mppe_key_change(mppe);
2595 			flushed = 1;
2596 		}
2597 		if (flushed)
2598 			pipex_mppe_setkey(mppe);
2599 	}
2600 
2601 	if (pktloss > 1000) {
2602 		pipex_session_log(session, LOG_DEBUG,
2603 		    "%d packets loss.", pktloss);
2604 	}
2605 
2606 	/* decrypt ppp payload */
2607 	for (m1 = m0; m1; m1 = m1->m_next) {
2608 		cp = mtod(m1, u_char *);
2609 		len = m1->m_len;
2610 		pipex_mppe_crypt(mppe, len, cp, cp);
2611 	}
2612 
2613 	if (!rewind) {
2614 		/* update coher_cnt */
2615 		mppe->coher_cnt++;
2616 		mppe->coher_cnt &= PIPEX_COHERENCY_CNT_MASK;
2617 	}
2618 
2619 	mtx_leave(&mppe->pxm_mtx);
2620 
2621 	if (m0->m_pkthdr.len < PIPEX_PPPMINLEN)
2622 		goto drop;
2623 
2624 	return (m0);
2625 drop:
2626 	m_freem(m0);
2627 	return (NULL);
2628 }
2629 
2630 struct mbuf *
pipex_mppe_output(struct mbuf * m0,struct pipex_session * session,uint16_t protocol)2631 pipex_mppe_output(struct mbuf *m0, struct pipex_session *session,
2632     uint16_t protocol)
2633 {
2634 	int encrypt, flushed, len;
2635 	struct mppe_header {
2636 		uint16_t coher_cnt;
2637 		uint16_t protocol;
2638 	} __packed *hdr;
2639 	u_char *cp;
2640 	struct pipex_mppe *mppe;
2641 	struct mbuf *m;
2642 
2643 	mppe = &session->mppe_send;
2644 
2645 	/*
2646 	 * create a deep-copy if the mbuf has a shared mbuf cluster.
2647 	 * this is required to handle cases of tcp retransmission.
2648 	 */
2649 	for (m = m0; m != NULL; m = m->m_next) {
2650 		if (M_READONLY(m)) {
2651 			m = m_dup_pkt(m0, max_linkhdr, M_NOWAIT);
2652 			m_freem(m0);
2653 			if (m == NULL)
2654 				return (NULL);
2655 			m0 = m;
2656 			break;
2657 		}
2658 	}
2659 	/* prepend mppe header */
2660 	M_PREPEND(m0, sizeof(struct mppe_header), M_NOWAIT);
2661 	if (m0 == NULL)
2662 		return (NULL);
2663 	hdr = mtod(m0, struct mppe_header *);
2664 	hdr->protocol = protocol;
2665 
2666 	/* check coherency counter */
2667 	flushed = 0;
2668 	encrypt = 1;
2669 
2670 	mtx_enter(&mppe->pxm_mtx);
2671 
2672 	if ((mppe->flags & PIPEX_MPPE_STATELESS) != 0) {
2673 		flushed = 1;
2674 		mppe_key_change(mppe);
2675 	} else {
2676 		if ((mppe->coher_cnt % 0x100) == 0xff) {
2677 			flushed = 1;
2678 			mppe_key_change(mppe);
2679 		} else if ((mppe->flags & PIPEX_MPPE_RESETREQ) != 0) {
2680 			flushed = 1;
2681 			mppe->flags &= ~PIPEX_MPPE_RESETREQ;
2682 		}
2683 	}
2684 
2685 	if (flushed)
2686 		pipex_mppe_setkey(mppe);
2687 
2688 	PIPEX_MPPE_DBG((session, LOG_DEBUG, "out coher_cnt=%03x %s%s",
2689 	    mppe->coher_cnt, (flushed) ? "[flushed]" : "",
2690 	    (encrypt) ? "[encrypt]" : ""));
2691 
2692 	/* setup header information */
2693 	hdr->coher_cnt = (mppe->coher_cnt++) & PIPEX_COHERENCY_CNT_MASK;
2694 	hdr->coher_cnt &= PIPEX_COHERENCY_CNT_MASK;
2695 	if (flushed)
2696 		hdr->coher_cnt |= 0x8000;
2697 	if (encrypt)
2698 		hdr->coher_cnt |= 0x1000;
2699 
2700 	hdr->protocol = htons(hdr->protocol);
2701 	hdr->coher_cnt = htons(hdr->coher_cnt);
2702 
2703 	/* encrypt chain */
2704 	for (m = m0; m; m = m->m_next) {
2705 		cp = mtod(m, u_char *);
2706 		len = m->m_len;
2707 		if (m == m0 && len > offsetof(struct mppe_header, protocol)) {
2708 			len -= offsetof(struct mppe_header, protocol);
2709 			cp += offsetof(struct mppe_header, protocol);
2710 		}
2711 		pipex_mppe_crypt(mppe, len, cp, cp);
2712 	}
2713 
2714 	mtx_leave(&mppe->pxm_mtx);
2715 
2716 	return (m0);
2717 }
2718 
2719 void
pipex_ccp_input(struct mbuf * m0,struct pipex_session * session)2720 pipex_ccp_input(struct mbuf *m0, struct pipex_session *session)
2721 {
2722 	u_char *cp;
2723 	int code, id, len;
2724 
2725 	if (m0->m_pkthdr.len < PPP_HDRLEN)
2726 		goto drop;
2727 	if ((m0 = m_pullup(m0, PPP_HDRLEN)) == NULL)
2728 		goto drop;
2729 
2730 	cp = mtod(m0, u_char *);
2731 	GETCHAR(code, cp);
2732 	GETCHAR(id, cp);
2733 	GETSHORT(len, cp);
2734 
2735 	switch (code) {
2736 	case CCP_RESETREQ:
2737 		PIPEX_DBG((session, LOG_DEBUG, "CCP RecvResetReq"));
2738 		mtx_enter(&session->mppe_send.pxm_mtx);
2739 		session->mppe_send.flags |= PIPEX_MPPE_RESETREQ;
2740 		mtx_leave(&session->mppe_send.pxm_mtx);
2741 #ifndef PIPEX_NO_CCP_RESETACK
2742 		PIPEX_DBG((session, LOG_DEBUG, "CCP SendResetAck"));
2743 		pipex_ccp_output(session, CCP_RESETACK, id);
2744 #endif
2745 		/* ignore error */
2746 		break;
2747 	case CCP_RESETACK:
2748 		PIPEX_DBG((session, LOG_DEBUG, "CCP RecvResetAck"));
2749 		break;
2750 	default:
2751 		PIPEX_DBG((session, LOG_DEBUG, "CCP Recv code=%d", code));
2752 		goto drop;
2753 	}
2754 	m_freem(m0);
2755 
2756 	return;
2757 drop:
2758 	m_freem(m0);
2759 	counters_inc(session->stat_counters, pxc_ierrors);
2760 }
2761 
2762 int
pipex_ccp_output(struct pipex_session * session,int code,int id)2763 pipex_ccp_output(struct pipex_session *session, int code, int id)
2764 {
2765 	u_char *cp;
2766 	struct mbuf *m;
2767 
2768 	MGETHDR(m, M_DONTWAIT, MT_DATA);
2769 	if (m == NULL) {
2770 		counters_inc(session->stat_counters, pxc_oerrors);
2771 		return (1);
2772 	}
2773 	m->m_pkthdr.len = m->m_len = 4;
2774 	cp = mtod(m, u_char *);
2775 	PUTCHAR(code, cp);
2776 	PUTCHAR(id, cp);
2777 	PUTSHORT(4, cp);
2778 
2779 	pipex_ppp_output(m, session, PPP_CCP);
2780 
2781 	return (0);
2782 }
2783 #endif
2784 /***********************************************************************
2785  * Miscellaneous functions
2786  ***********************************************************************/
2787 /* adapted from FreeBSD:src/usr.sbin/ppp/tcpmss.c */
2788 /*
2789  * Copyright (c) 2000 Ruslan Ermilov and Brian Somers <brian@Awfulhak.org>
2790  * All rights reserved.
2791  *
2792  * Redistribution and use in source and binary forms, with or without
2793  * modification, are permitted provided that the following conditions
2794  * are met:
2795  * 1. Redistributions of source code must retain the above copyright
2796  *    notice, this list of conditions and the following disclaimer.
2797  * 2. Redistributions in binary form must reproduce the above copyright
2798  *    notice, this list of conditions and the following disclaimer in the
2799  *    documentation and/or other materials provided with the distribution.
2800  *
2801  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
2802  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2803  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2804  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2805  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2806  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2807  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2808  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2809  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2810  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2811  * SUCH DAMAGE.
2812  *
2813  * $FreeBSD: src/usr.sbin/ppp/tcpmss.c,v 1.1.4.3 2001/07/19 11:39:54 brian Exp $
2814  */
2815 #define TCP_OPTLEN_IN_SEGMENT	12	/* timestamp option and padding */
2816 #define MAXMSS(mtu) (mtu - sizeof(struct ip) - sizeof(struct tcphdr) - \
2817     TCP_OPTLEN_IN_SEGMENT)
2818 /*
2819  * The following macro is used to update an internet checksum.  "acc" is a
2820  * 32-bit accumulation of all the changes to the checksum (adding in old
2821  * 16-bit words and subtracting out new words), and "cksum" is the checksum
2822  * value to be updated.
2823  */
2824 #define ADJUST_CHECKSUM(acc, cksum) {			\
2825 	acc += cksum;					\
2826 	if (acc < 0) {					\
2827 		acc = -acc;				\
2828 		acc = (acc >> 16) + (acc & 0xffff);	\
2829 		acc += acc >> 16;			\
2830 		cksum = (u_short) ~acc;			\
2831 	} else {					\
2832 		acc = (acc >> 16) + (acc & 0xffff);	\
2833 		acc += acc >> 16;			\
2834 		cksum = (u_short) acc;			\
2835 	}						\
2836 }
2837 
2838 /*
2839  * Rewrite max-segment-size TCP option to avoid PMTU blackhole issues.
2840  * The mtu parameter should be the MTU bottleneck (as far as we know)
2841  * on the link between the source and the destination.
2842  */
2843 struct mbuf *
adjust_tcp_mss(struct mbuf * m0,int mtu)2844 adjust_tcp_mss(struct mbuf *m0, int mtu)
2845 {
2846 	int opt, optlen, acc, mss, maxmss, lpktp;
2847 	struct ip *pip;
2848 	struct tcphdr *th;
2849 	u_char *pktp, *mssp;
2850 	u_int16_t ip_off;
2851 
2852 	lpktp = sizeof(struct ip) + sizeof(struct tcphdr) + PIPEX_TCP_OPTLEN;
2853 	lpktp = MIN(lpktp, m0->m_pkthdr.len);
2854 
2855 	PIPEX_PULLUP(m0, lpktp);
2856 	if (m0 == NULL)
2857 		goto drop;
2858 
2859 	pktp = mtod(m0, char *);
2860 	pip = (struct ip *)pktp;
2861 	ip_off = ntohs(pip->ip_off);
2862 
2863 	/* Non TCP or fragmented packet must not have a MSS option */
2864 	if (pip->ip_p != IPPROTO_TCP ||
2865 	    (ip_off & IP_MF) != 0 || (ip_off & IP_OFFMASK) != 0)
2866 		goto handled;
2867 
2868 	pktp += pip->ip_hl << 2;
2869 	lpktp -= pip->ip_hl << 2;
2870 
2871 	/* packet is broken */
2872 	if (sizeof(struct tcphdr) > lpktp)
2873 		goto drop;
2874 	th = (struct tcphdr *)pktp;
2875 
2876 	/*
2877 	 * As RFC 973, a MSS field must only be sent in the initial
2878 	 * connection request(it must be with SYN).
2879 	 */
2880 	if ((th->th_flags & TH_SYN) == 0)
2881 		goto handled;
2882 
2883 	lpktp = MIN(th->th_off << 4, lpktp);
2884 
2885 	pktp += sizeof(struct tcphdr);
2886 	lpktp -= sizeof(struct tcphdr);
2887 	while (lpktp >= TCPOLEN_MAXSEG) {
2888 		GETCHAR(opt, pktp);
2889 		switch (opt) {
2890 		case TCPOPT_MAXSEG:
2891 			GETCHAR(optlen, pktp);
2892 			mssp = pktp;		/* mss place holder */
2893 			GETSHORT(mss, pktp);
2894 			maxmss = MAXMSS(mtu);
2895 			if (mss > maxmss) {
2896 				PIPEX_DBG((NULL, LOG_DEBUG,
2897 				    "change tcp-mss %d => %d", mss, maxmss));
2898 				PUTSHORT(maxmss, mssp);
2899 				acc = htons(mss);
2900 				acc -= htons(maxmss);
2901 				ADJUST_CHECKSUM(acc, th->th_sum);
2902 			}
2903 			goto handled;
2904 			/* NOTREACHED */
2905 		case TCPOPT_EOL:
2906 			goto handled;
2907 			/* NOTREACHED */
2908 		case TCPOPT_NOP:
2909 			lpktp--;
2910 			break;
2911 		default:
2912 			GETCHAR(optlen, pktp);
2913 			if (optlen < 2)	/* packet is broken */
2914 				goto drop;
2915 			pktp += optlen - 2;
2916 			lpktp -= optlen;
2917 			break;
2918 		}
2919 	}
2920 
2921 handled:
2922 	return (m0);
2923 
2924 drop:
2925 	m_freem(m0);
2926 	return (NULL);
2927 }
2928 
2929 /*
2930  *  Check whether a packet should reset idle timer
2931  *  Returns 1 to don't reset timer (i.e. the packet is "idle" packet)
2932  */
2933 struct mbuf *
ip_is_idle_packet(struct mbuf * m0,int * ris_idle)2934 ip_is_idle_packet(struct mbuf *m0, int *ris_idle)
2935 {
2936 	u_int16_t ip_off;
2937 	const struct udphdr *uh;
2938 	struct ip *pip;
2939 	int len;
2940 
2941 	/* pullup ip header */
2942 	len = sizeof(struct ip);
2943 	PIPEX_PULLUP(m0, len);
2944 	if (m0 == NULL)
2945 		goto error;
2946 	pip = mtod(m0, struct ip *);
2947 
2948 	/*
2949 	 * the packet which fragmentations was not the idle packet.
2950 	 */
2951 	ip_off = ntohs(pip->ip_off);
2952 	if ((ip_off & IP_MF) || ((ip_off & IP_OFFMASK) != 0))
2953 		goto is_active;
2954 
2955 	switch (pip->ip_p) {
2956 	case IPPROTO_IGMP:
2957 		goto is_active;
2958 	case IPPROTO_ICMP:
2959 		len = pip->ip_hl * 4 + 8;
2960 		PIPEX_PULLUP(m0, len);
2961 		if (m0 == NULL)
2962 			goto error;
2963 		pip = mtod(m0, struct ip *);
2964 
2965 		switch (((unsigned char *) pip)[pip->ip_hl * 4]) {
2966 		case 0:	/* Echo Reply */
2967 		case 8:	/* Echo Request */
2968 			goto is_active;
2969 		default:
2970 			goto is_idle;
2971 		}
2972 
2973 	case IPPROTO_UDP:
2974 	case IPPROTO_TCP:
2975 		len = pip->ip_hl * 4 + sizeof(struct udphdr);
2976 		PIPEX_PULLUP(m0, len);
2977 		if (m0 == NULL)
2978 			goto error;
2979 		pip = mtod(m0, struct ip *);
2980 		uh = (struct udphdr *)(mtod(m0, caddr_t) + pip->ip_hl * 4);
2981 
2982 		switch (ntohs(uh->uh_sport)) {
2983 		case 53:	/* DOMAIN */
2984 		case 67:	/* BOOTPS */
2985 		case 68:	/* BOOTPC */
2986 		case 123:	/* NTP */
2987 		case 137:	/* NETBIOS-NS */
2988 		case 520:	/* RIP */
2989 			goto is_idle;
2990 		}
2991 		switch (ntohs(uh->uh_dport)) {
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 		goto is_active;
3001 	default:
3002 		goto is_active;
3003 	}
3004 
3005 is_active:
3006 	*ris_idle = 0;
3007 	return (m0);
3008 
3009 is_idle:
3010 	*ris_idle = 1;
3011 	return (m0);
3012 
3013 error:
3014 	return (NULL);
3015 }
3016 
3017 void
pipex_session_log(struct pipex_session * session,int prio,const char * fmt,...)3018 pipex_session_log(struct pipex_session *session, int prio, const char *fmt, ...)
3019 {
3020 	char logbuf[1024];
3021 	va_list ap;
3022 
3023 	logpri(prio);
3024 	if (session != NULL) {
3025 		struct ifnet *ifp;
3026 
3027 		ifp = if_get(session->ifindex);
3028 		addlog("pipex: ppp=%d iface=%s protocol=%s id=%d ",
3029 		    session->ppp_id,
3030 		    ifp? ifp->if_xname : "Unknown",
3031 		    (session->protocol == PIPEX_PROTO_PPPOE)? "PPPoE" :
3032 		    (session->protocol == PIPEX_PROTO_PPTP)? "PPTP" :
3033 		    (session->protocol == PIPEX_PROTO_L2TP) ? "L2TP" :
3034 		    "Unknown", session->session_id);
3035 		if_put(ifp);
3036 	} else
3037 		addlog("pipex: ");
3038 
3039 	va_start(ap, fmt);
3040 	vsnprintf(logbuf, sizeof(logbuf), fmt, ap);
3041 	va_end(ap);
3042 	addlog("%s\n", logbuf);
3043 }
3044 
3045 uint32_t
pipex_sockaddr_hash_key(struct sockaddr * sa)3046 pipex_sockaddr_hash_key(struct sockaddr *sa)
3047 {
3048 	switch (sa->sa_family) {
3049 	case AF_INET:
3050 		return ntohl(satosin(sa)->sin_addr.s_addr);
3051 	case AF_INET6:
3052 		return ntohl(satosin6(sa)->sin6_addr.s6_addr32[3]);
3053 	}
3054 	panic("pipex_sockaddr_hash_key: unknown address family");
3055 	return (0);
3056 }
3057 
3058 /*
3059  * Compare struct sockaddr_in{,6} with the address only.
3060  * The port number is not covered.
3061  */
3062 int
pipex_sockaddr_compar_addr(struct sockaddr * a,struct sockaddr * b)3063 pipex_sockaddr_compar_addr(struct sockaddr *a, struct sockaddr *b)
3064 {
3065 	int cmp;
3066 
3067 	cmp = b->sa_family - a->sa_family;
3068 	if (cmp != 0)
3069 		return cmp;
3070 	switch (a->sa_family) {
3071 	case AF_INET:
3072 		return (satosin(b)->sin_addr.s_addr -
3073 		    satosin(a)->sin_addr.s_addr);
3074 	case AF_INET6:
3075 		cmp = (satosin6(b)->sin6_scope_id - satosin6(a)->sin6_scope_id);
3076 		if (cmp != 0)
3077 			return cmp;
3078 		return (memcmp(&satosin6(a)->sin6_addr,
3079 		    &satosin6(b)->sin6_addr,
3080 		    sizeof(struct in6_addr)));
3081 	}
3082 	panic("pipex_sockaddr_compar_addr: unknown address family");
3083 
3084 	return (-1);
3085 }
3086 
3087 int
pipex_sysctl(int * name,u_int namelen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)3088 pipex_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
3089     size_t newlen)
3090 {
3091 	switch (name[0]) {
3092 	case PIPEXCTL_ENABLE:
3093 		if (namelen != 1)
3094 			return (ENOTDIR);
3095 		return (sysctl_int_bounded(oldp, oldlenp, newp, newlen,
3096 		    &pipex_enable, 0, 1));
3097 	default:
3098 		return (ENOPROTOOPT);
3099 	}
3100 	/* NOTREACHED */
3101 }
3102