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