2022-09-03 05:47:59 +03:00
|
|
|
/* $NetBSD: if_ppp.c,v 1.172 2022/09/03 02:47:59 thorpej Exp $ */
|
1997-03-12 23:26:46 +03:00
|
|
|
/* Id: if_ppp.c,v 1.6 1997/03/04 03:33:00 paulus Exp */
|
1994-06-29 10:29:24 +04:00
|
|
|
|
1993-08-14 10:29:28 +04:00
|
|
|
/*
|
|
|
|
* if_ppp.c - Point-to-Point Protocol (PPP) Asynchronous driver.
|
|
|
|
*
|
2002-07-02 02:09:31 +04:00
|
|
|
* Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved.
|
1993-08-14 10:29:28 +04:00
|
|
|
*
|
2002-07-02 02:09:31 +04:00
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
*
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
*
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in
|
|
|
|
* the documentation and/or other materials provided with the
|
|
|
|
* distribution.
|
|
|
|
*
|
|
|
|
* 3. The name "Carnegie Mellon University" must not be used to
|
|
|
|
* endorse or promote products derived from this software without
|
|
|
|
* prior written permission. For permission or any legal
|
|
|
|
* details, please contact
|
|
|
|
* Office of Technology Transfer
|
|
|
|
* Carnegie Mellon University
|
|
|
|
* 5000 Forbes Avenue
|
|
|
|
* Pittsburgh, PA 15213-3890
|
|
|
|
* (412) 268-4387, fax: (412) 268-7395
|
|
|
|
* tech-transfer@andrew.cmu.edu
|
|
|
|
*
|
|
|
|
* 4. Redistributions of any form whatsoever must retain the following
|
|
|
|
* acknowledgment:
|
|
|
|
* "This product includes software developed by Computing Services
|
|
|
|
* at Carnegie Mellon University (http://www.cmu.edu/computing/)."
|
1993-08-14 10:29:28 +04:00
|
|
|
*
|
2002-07-02 02:09:31 +04:00
|
|
|
* CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
|
|
|
|
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
|
|
* AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
|
|
|
|
* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
|
|
|
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
|
|
|
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
1993-08-14 10:29:28 +04:00
|
|
|
*
|
|
|
|
* Based on:
|
|
|
|
* @(#)if_sl.c 7.6.1.2 (Berkeley) 2/15/89
|
|
|
|
*
|
|
|
|
* Copyright (c) 1987 Regents of the University of California.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms are permitted
|
|
|
|
* provided that the above copyright notice and this paragraph are
|
|
|
|
* duplicated in all such forms and that any documentation,
|
|
|
|
* advertising materials, and other materials related to such
|
|
|
|
* distribution and use acknowledge that the software was developed
|
|
|
|
* by the University of California, Berkeley. The name of the
|
|
|
|
* University may not be used to endorse or promote products derived
|
|
|
|
* from this software without specific prior written permission.
|
|
|
|
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
|
|
|
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
|
|
|
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
*
|
|
|
|
* Serial Line interface
|
|
|
|
*
|
|
|
|
* Rick Adams
|
|
|
|
* Center for Seismic Studies
|
|
|
|
* 1300 N 17th Street, Suite 1450
|
|
|
|
* Arlington, Virginia 22209
|
|
|
|
* (703)276-7900
|
|
|
|
* rick@seismo.ARPA
|
|
|
|
* seismo!rick
|
|
|
|
*
|
|
|
|
* Pounded on heavily by Chris Torek (chris@mimsy.umd.edu, umcp-cs!chris).
|
|
|
|
* Converted to 4.3BSD Beta by Chris Torek.
|
|
|
|
* Other changes made at Berkeley, based in part on code by Kirk Smith.
|
|
|
|
*
|
|
|
|
* Converted to 4.3BSD+ 386BSD by Brad Parker (brad@cayman.com)
|
|
|
|
* Added VJ tcp header compression; more unified ioctls
|
|
|
|
*
|
|
|
|
* Extensively modified by Paul Mackerras (paulus@cs.anu.edu.au).
|
|
|
|
* Cleaned up a lot of the mbuf-related code to fix bugs that
|
|
|
|
* caused system crashes and packet corruption. Changed pppstart
|
|
|
|
* so that it doesn't just give up with a collision if the whole
|
|
|
|
* packet doesn't fit in the output ring buffer.
|
|
|
|
*
|
1993-08-31 04:05:27 +04:00
|
|
|
* Added priority queueing for interactive IP packets, following
|
|
|
|
* the model of if_sl.c, plus hooks for bpf.
|
|
|
|
* Paul Mackerras (paulus@cs.anu.edu.au).
|
1993-08-14 10:29:28 +04:00
|
|
|
*/
|
|
|
|
|
1993-08-31 04:05:27 +04:00
|
|
|
/* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */
|
1995-07-04 10:28:17 +04:00
|
|
|
/* from NetBSD: if_ppp.c,v 1.15.2.2 1994/07/28 05:17:58 cgd Exp */
|
1993-08-31 04:05:27 +04:00
|
|
|
|
2001-04-14 03:29:55 +04:00
|
|
|
/*
|
|
|
|
* XXX IMP ME HARDER
|
|
|
|
*
|
|
|
|
* This is an explanation of that comment. This code used to use
|
|
|
|
* splimp() to block both network and tty interrupts. However,
|
|
|
|
* that call is deprecated. So, we have replaced the uses of
|
|
|
|
* splimp() with splhigh() in order to applomplish what it needs
|
|
|
|
* to accomplish, and added that happy little comment.
|
|
|
|
*/
|
|
|
|
|
2001-11-13 02:49:33 +03:00
|
|
|
#include <sys/cdefs.h>
|
2022-09-03 05:47:59 +03:00
|
|
|
__KERNEL_RCSID(0, "$NetBSD: if_ppp.c,v 1.172 2022/09/03 02:47:59 thorpej Exp $");
|
2000-10-04 06:51:18 +04:00
|
|
|
|
2015-08-25 01:21:26 +03:00
|
|
|
#ifdef _KERNEL_OPT
|
2016-08-06 05:35:05 +03:00
|
|
|
#include "ppp.h"
|
2000-10-06 08:49:53 +04:00
|
|
|
#include "opt_inet.h"
|
|
|
|
#include "opt_gateway.h"
|
|
|
|
#include "opt_ppp.h"
|
2015-08-25 01:21:26 +03:00
|
|
|
#endif
|
2000-10-06 08:49:53 +04:00
|
|
|
|
2000-10-02 07:54:10 +04:00
|
|
|
#ifdef INET
|
1993-08-14 10:29:28 +04:00
|
|
|
#define VJC
|
2000-10-02 07:54:10 +04:00
|
|
|
#endif
|
1995-07-04 10:28:17 +04:00
|
|
|
#define PPP_COMPRESS
|
1993-08-14 10:29:28 +04:00
|
|
|
|
1993-12-18 03:40:47 +03:00
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/proc.h>
|
|
|
|
#include <sys/mbuf.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <sys/ioctl.h>
|
|
|
|
#include <sys/kernel.h>
|
1996-02-14 00:59:53 +03:00
|
|
|
#include <sys/systm.h>
|
1996-03-15 05:28:00 +03:00
|
|
|
#include <sys/time.h>
|
|
|
|
#include <sys/malloc.h>
|
2008-11-25 05:40:36 +03:00
|
|
|
#include <sys/module.h>
|
|
|
|
#include <sys/mutex.h>
|
2008-11-30 02:15:20 +03:00
|
|
|
#include <sys/once.h>
|
2005-11-27 08:35:52 +03:00
|
|
|
#include <sys/conf.h>
|
2006-05-15 01:19:33 +04:00
|
|
|
#include <sys/kauth.h>
|
2007-10-08 20:18:02 +04:00
|
|
|
#include <sys/intr.h>
|
2008-04-24 15:38:36 +04:00
|
|
|
#include <sys/socketvar.h>
|
2016-08-06 05:35:05 +03:00
|
|
|
#include <sys/device.h>
|
|
|
|
#include <sys/module.h>
|
1995-07-04 10:28:17 +04:00
|
|
|
|
1993-12-18 03:40:47 +03:00
|
|
|
#include <net/if.h>
|
|
|
|
#include <net/if_types.h>
|
|
|
|
#include <net/route.h>
|
1993-08-14 10:29:28 +04:00
|
|
|
|
1993-12-18 03:40:47 +03:00
|
|
|
#include <netinet/in.h>
|
|
|
|
#include <netinet/in_systm.h>
|
|
|
|
#include <netinet/in_var.h>
|
2000-10-02 07:54:10 +04:00
|
|
|
#ifdef INET
|
1993-12-18 03:40:47 +03:00
|
|
|
#include <netinet/ip.h>
|
1993-08-14 10:29:28 +04:00
|
|
|
#endif
|
|
|
|
|
1993-12-18 03:40:47 +03:00
|
|
|
#include <net/bpf.h>
|
1998-09-03 18:12:36 +04:00
|
|
|
#include <net/slip.h>
|
|
|
|
|
1993-08-14 10:29:28 +04:00
|
|
|
#ifdef VJC
|
1994-05-08 16:33:49 +04:00
|
|
|
#include <net/slcompress.h>
|
1993-08-14 10:29:28 +04:00
|
|
|
#endif
|
|
|
|
|
1995-07-04 10:28:17 +04:00
|
|
|
#include <net/ppp_defs.h>
|
1994-05-08 16:33:49 +04:00
|
|
|
#include <net/if_ppp.h>
|
1995-07-04 10:28:17 +04:00
|
|
|
#include <net/if_pppvar.h>
|
2007-10-19 15:59:34 +04:00
|
|
|
#include <sys/cpu.h>
|
1993-08-14 10:29:28 +04:00
|
|
|
|
1995-07-04 10:28:17 +04:00
|
|
|
#ifdef PPP_COMPRESS
|
|
|
|
#define PACKETPTR struct mbuf *
|
|
|
|
#include <net/ppp-comp.h>
|
|
|
|
#endif
|
1993-08-14 10:29:28 +04:00
|
|
|
|
2015-08-20 14:18:53 +03:00
|
|
|
#include "ioconf.h"
|
|
|
|
|
2007-03-04 08:59:00 +03:00
|
|
|
static int pppsioctl(struct ifnet *, u_long, void *);
|
2005-12-12 02:05:24 +03:00
|
|
|
static void ppp_requeue(struct ppp_softc *);
|
|
|
|
static void ppp_ccp(struct ppp_softc *, struct mbuf *m, int rcvd);
|
|
|
|
static void ppp_ccp_closed(struct ppp_softc *);
|
|
|
|
static void ppp_inproc(struct ppp_softc *, struct mbuf *);
|
|
|
|
static void pppdumpm(struct mbuf *m0);
|
2002-03-05 07:12:57 +03:00
|
|
|
#ifdef ALTQ
|
2005-12-12 02:05:24 +03:00
|
|
|
static void ppp_ifstart(struct ifnet *ifp);
|
2002-03-05 07:12:57 +03:00
|
|
|
#endif
|
1993-08-14 10:29:28 +04:00
|
|
|
|
2005-12-12 02:05:24 +03:00
|
|
|
static void pppintr(void *);
|
2001-01-15 19:33:30 +03:00
|
|
|
|
2016-08-06 05:35:05 +03:00
|
|
|
extern struct linesw ppp_disc;
|
|
|
|
|
1993-08-31 04:05:27 +04:00
|
|
|
/*
|
1999-01-10 00:47:09 +03:00
|
|
|
* We define two link layer specific mbuf flags, to mark high-priority
|
|
|
|
* packets for output, and received packets following lost/corrupted
|
|
|
|
* packets.
|
1993-08-31 04:05:27 +04:00
|
|
|
*/
|
1999-01-10 00:47:09 +03:00
|
|
|
#define M_HIGHPRI M_LINK0 /* output packet for sc_fastq */
|
|
|
|
#define M_ERRMARK M_LINK1 /* rx packet following lost/corrupted pkt */
|
1995-07-04 10:28:17 +04:00
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
static int ppp_clone_create(struct if_clone *, int);
|
|
|
|
static int ppp_clone_destroy(struct ifnet *);
|
2004-12-05 07:15:16 +03:00
|
|
|
|
|
|
|
static struct ppp_softc *ppp_create(const char *, int);
|
|
|
|
|
2019-01-25 11:51:29 +03:00
|
|
|
static struct {
|
2019-06-25 15:30:50 +03:00
|
|
|
LIST_HEAD(ppp_sclist, ppp_softc) list;
|
2019-01-25 11:51:29 +03:00
|
|
|
kmutex_t lock;
|
|
|
|
} ppp_softcs __cacheline_aligned;
|
2004-12-05 07:15:16 +03:00
|
|
|
|
|
|
|
struct if_clone ppp_cloner =
|
|
|
|
IF_CLONE_INITIALIZER("ppp", ppp_clone_create, ppp_clone_destroy);
|
|
|
|
|
1995-07-04 10:28:17 +04:00
|
|
|
#ifdef PPP_COMPRESS
|
2008-11-25 05:40:36 +03:00
|
|
|
static LIST_HEAD(, compressor) ppp_compressors = { NULL };
|
|
|
|
static kmutex_t ppp_compressors_mtx;
|
1995-07-04 10:28:17 +04:00
|
|
|
|
2008-11-30 02:15:20 +03:00
|
|
|
static int ppp_compressor_init(void);
|
2016-08-06 05:35:05 +03:00
|
|
|
static int ppp_compressor_destroy(void);
|
2008-11-25 05:40:36 +03:00
|
|
|
static struct compressor *ppp_get_compressor(uint8_t);
|
2008-11-30 02:15:20 +03:00
|
|
|
static void ppp_compressor_rele(struct compressor *);
|
1995-07-04 10:28:17 +04:00
|
|
|
#endif /* PPP_COMPRESS */
|
|
|
|
|
1997-03-12 23:26:46 +03:00
|
|
|
|
1993-08-14 10:29:28 +04:00
|
|
|
/*
|
|
|
|
* Called from boot code to establish ppp interfaces.
|
|
|
|
*/
|
|
|
|
void
|
2015-08-20 14:18:53 +03:00
|
|
|
pppattach(int n __unused)
|
1993-08-14 10:29:28 +04:00
|
|
|
{
|
2016-08-06 05:35:05 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Nothing to do here, initialization is handled by the
|
|
|
|
* module initialization code in pppinit() below).
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
pppinit(void)
|
|
|
|
{
|
2016-08-07 20:38:33 +03:00
|
|
|
/* Init the compressor sub-sub-system */
|
|
|
|
ppp_compressor_init();
|
2005-11-27 08:35:52 +03:00
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
if (ttyldisc_attach(&ppp_disc) != 0)
|
2016-08-06 15:48:23 +03:00
|
|
|
panic("%s", __func__);
|
2011-08-07 17:51:37 +04:00
|
|
|
|
2019-01-25 11:51:29 +03:00
|
|
|
mutex_init(&ppp_softcs.lock, MUTEX_DEFAULT, IPL_NONE);
|
|
|
|
LIST_INIT(&ppp_softcs.list);
|
2014-07-01 19:03:58 +04:00
|
|
|
if_clone_attach(&ppp_cloner);
|
2016-08-06 05:35:05 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
pppdetach(void)
|
|
|
|
{
|
2016-08-06 15:48:23 +03:00
|
|
|
int error = 0;
|
2016-08-06 05:35:05 +03:00
|
|
|
|
2019-01-25 11:51:29 +03:00
|
|
|
if (!LIST_EMPTY(&ppp_softcs.list))
|
2016-08-06 05:35:05 +03:00
|
|
|
error = EBUSY;
|
2016-08-06 15:48:23 +03:00
|
|
|
|
2016-08-06 05:35:05 +03:00
|
|
|
if (error == 0)
|
|
|
|
error = ttyldisc_detach(&ppp_disc);
|
2016-08-06 15:48:23 +03:00
|
|
|
|
2016-08-07 20:38:33 +03:00
|
|
|
if (error == 0) {
|
2019-01-25 11:51:29 +03:00
|
|
|
mutex_destroy(&ppp_softcs.lock);
|
2016-08-07 20:38:33 +03:00
|
|
|
if_clone_detach(&ppp_cloner);
|
|
|
|
ppp_compressor_destroy();
|
|
|
|
}
|
2016-08-07 01:54:34 +03:00
|
|
|
|
2016-08-06 05:35:05 +03:00
|
|
|
return error;
|
2004-12-05 07:15:16 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static struct ppp_softc *
|
|
|
|
ppp_create(const char *name, int unit)
|
|
|
|
{
|
2014-07-01 19:03:58 +04:00
|
|
|
struct ppp_softc *sc, *sci, *scl = NULL;
|
2004-12-05 07:15:16 +03:00
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
sc = malloc(sizeof(*sc), M_DEVBUF, M_WAIT|M_ZERO);
|
2004-12-05 07:15:16 +03:00
|
|
|
|
2019-01-25 11:51:29 +03:00
|
|
|
mutex_enter(&ppp_softcs.lock);
|
2014-07-01 19:03:58 +04:00
|
|
|
if (unit == -1) {
|
|
|
|
int i = 0;
|
2019-01-25 11:51:29 +03:00
|
|
|
LIST_FOREACH(sci, &ppp_softcs.list, sc_iflist) {
|
2014-07-01 19:03:58 +04:00
|
|
|
scl = sci;
|
|
|
|
if (i < sci->sc_unit) {
|
|
|
|
unit = i;
|
|
|
|
break;
|
|
|
|
} else {
|
2004-12-05 07:15:16 +03:00
|
|
|
#ifdef DIAGNOSTIC
|
2014-07-01 19:03:58 +04:00
|
|
|
KASSERT(i == sci->sc_unit);
|
2004-12-05 07:15:16 +03:00
|
|
|
#endif
|
2014-07-01 19:03:58 +04:00
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (unit == -1)
|
|
|
|
unit = i;
|
|
|
|
} else {
|
2019-01-25 11:51:29 +03:00
|
|
|
LIST_FOREACH(sci, &ppp_softcs.list, sc_iflist) {
|
2014-07-01 19:03:58 +04:00
|
|
|
scl = sci;
|
|
|
|
if (unit < sci->sc_unit)
|
|
|
|
break;
|
|
|
|
else if (unit == sci->sc_unit) {
|
|
|
|
free(sc, M_DEVBUF);
|
2019-01-25 11:51:29 +03:00
|
|
|
mutex_exit(&ppp_softcs.lock);
|
2014-07-01 19:03:58 +04:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
2004-12-05 07:15:16 +03:00
|
|
|
}
|
2014-07-01 19:03:58 +04:00
|
|
|
|
|
|
|
if (sci != NULL)
|
|
|
|
LIST_INSERT_BEFORE(sci, sc, sc_iflist);
|
|
|
|
else if (scl != NULL)
|
|
|
|
LIST_INSERT_AFTER(scl, sc, sc_iflist);
|
|
|
|
else
|
2019-01-25 11:51:29 +03:00
|
|
|
LIST_INSERT_HEAD(&ppp_softcs.list, sc, sc_iflist);
|
2014-07-01 19:03:58 +04:00
|
|
|
|
2019-01-25 11:51:29 +03:00
|
|
|
mutex_exit(&ppp_softcs.lock);
|
2014-07-01 19:03:58 +04:00
|
|
|
|
|
|
|
if_initname(&sc->sc_if, name, sc->sc_unit = unit);
|
|
|
|
callout_init(&sc->sc_timo_ch, 0);
|
|
|
|
sc->sc_if.if_softc = sc;
|
|
|
|
sc->sc_if.if_mtu = PPP_MTU;
|
|
|
|
sc->sc_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST;
|
|
|
|
sc->sc_if.if_type = IFT_PPP;
|
|
|
|
sc->sc_if.if_hdrlen = PPP_HDRLEN;
|
|
|
|
sc->sc_if.if_dlt = DLT_NULL;
|
|
|
|
sc->sc_if.if_ioctl = pppsioctl;
|
|
|
|
sc->sc_if.if_output = pppoutput;
|
2002-03-05 07:12:57 +03:00
|
|
|
#ifdef ALTQ
|
2014-07-01 19:03:58 +04:00
|
|
|
sc->sc_if.if_start = ppp_ifstart;
|
2002-03-05 07:12:57 +03:00
|
|
|
#endif
|
2014-07-01 19:03:58 +04:00
|
|
|
IFQ_SET_MAXLEN(&sc->sc_if.if_snd, IFQ_MAXLEN);
|
2022-08-27 22:04:43 +03:00
|
|
|
IFQ_SET_MAXLEN(&sc->sc_inq, IFQ_MAXLEN);
|
|
|
|
IFQ_SET_MAXLEN(&sc->sc_fastq, IFQ_MAXLEN);
|
|
|
|
IFQ_SET_MAXLEN(&sc->sc_rawq, IFQ_MAXLEN);
|
|
|
|
|
2022-08-27 22:15:00 +03:00
|
|
|
IFQ_LOCK_INIT(&sc->sc_fastq);
|
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
/* Ratio of 1:2 packets between the regular and the fast queue */
|
2022-07-06 11:06:59 +03:00
|
|
|
sc->sc_maxfastq = 2;
|
2014-07-01 19:03:58 +04:00
|
|
|
IFQ_SET_READY(&sc->sc_if.if_snd);
|
|
|
|
if_attach(&sc->sc_if);
|
|
|
|
if_alloc_sadl(&sc->sc_if);
|
|
|
|
bpf_attach(&sc->sc_if, DLT_NULL, 0);
|
|
|
|
return sc;
|
2004-12-05 07:15:16 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
ppp_clone_create(struct if_clone *ifc, int unit)
|
|
|
|
{
|
2014-07-01 19:03:58 +04:00
|
|
|
return ppp_create(ifc->ifc_name, unit) == NULL ? EEXIST : 0;
|
2004-12-05 07:15:16 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
ppp_clone_destroy(struct ifnet *ifp)
|
|
|
|
{
|
2014-07-01 19:03:58 +04:00
|
|
|
struct ppp_softc *sc = (struct ppp_softc *)ifp->if_softc;
|
2004-12-05 07:15:16 +03:00
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
if (sc->sc_devp != NULL)
|
|
|
|
return EBUSY; /* Not removing it */
|
2004-12-05 07:15:16 +03:00
|
|
|
|
2019-01-25 11:51:29 +03:00
|
|
|
mutex_enter(&ppp_softcs.lock);
|
2014-07-01 19:03:58 +04:00
|
|
|
LIST_REMOVE(sc, sc_iflist);
|
2019-01-25 11:51:29 +03:00
|
|
|
mutex_exit(&ppp_softcs.lock);
|
2004-12-05 07:15:16 +03:00
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
bpf_detach(ifp);
|
|
|
|
if_detach(ifp);
|
2004-12-05 07:15:16 +03:00
|
|
|
|
2022-08-27 22:15:00 +03:00
|
|
|
IFQ_LOCK_DESTROY(&sc->sc_fastq);
|
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
free(sc, M_DEVBUF);
|
|
|
|
return 0;
|
1993-08-14 10:29:28 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1994-05-08 16:33:49 +04:00
|
|
|
* Allocate a ppp interface unit and initialize it.
|
|
|
|
*/
|
|
|
|
struct ppp_softc *
|
2005-12-12 02:05:24 +03:00
|
|
|
pppalloc(pid_t pid)
|
1994-05-08 16:33:49 +04:00
|
|
|
{
|
2014-07-01 19:03:58 +04:00
|
|
|
struct ppp_softc *sc = NULL, *scf;
|
|
|
|
int i;
|
|
|
|
|
2019-01-25 11:51:29 +03:00
|
|
|
mutex_enter(&ppp_softcs.lock);
|
|
|
|
LIST_FOREACH(scf, &ppp_softcs.list, sc_iflist) {
|
2014-07-01 19:03:58 +04:00
|
|
|
if (scf->sc_xfer == pid) {
|
|
|
|
scf->sc_xfer = 0;
|
2019-01-25 11:51:29 +03:00
|
|
|
mutex_exit(&ppp_softcs.lock);
|
2014-07-01 19:03:58 +04:00
|
|
|
return scf;
|
|
|
|
}
|
|
|
|
if (scf->sc_devp == NULL && sc == NULL)
|
|
|
|
sc = scf;
|
|
|
|
}
|
2019-01-25 11:51:29 +03:00
|
|
|
mutex_exit(&ppp_softcs.lock);
|
2014-07-01 19:03:58 +04:00
|
|
|
|
|
|
|
if (sc == NULL)
|
|
|
|
sc = ppp_create(ppp_cloner.ifc_name, -1);
|
|
|
|
|
|
|
|
sc->sc_si = softint_establish(SOFTINT_NET, pppintr, sc);
|
|
|
|
if (sc->sc_si == NULL) {
|
|
|
|
printf("%s: unable to establish softintr\n",
|
|
|
|
sc->sc_if.if_xname);
|
2022-07-06 11:06:59 +03:00
|
|
|
return NULL;
|
1994-05-08 16:33:49 +04:00
|
|
|
}
|
2014-07-01 19:03:58 +04:00
|
|
|
sc->sc_flags = 0;
|
|
|
|
sc->sc_mru = PPP_MRU;
|
|
|
|
sc->sc_relinq = NULL;
|
|
|
|
(void)memset(&sc->sc_stats, 0, sizeof(sc->sc_stats));
|
1994-05-08 16:33:49 +04:00
|
|
|
#ifdef VJC
|
2014-07-01 19:03:58 +04:00
|
|
|
sc->sc_comp = malloc(sizeof(struct slcompress), M_DEVBUF, M_NOWAIT);
|
|
|
|
if (sc->sc_comp)
|
|
|
|
sl_compress_init(sc->sc_comp);
|
1994-05-08 16:33:49 +04:00
|
|
|
#endif
|
1995-07-04 10:28:17 +04:00
|
|
|
#ifdef PPP_COMPRESS
|
2014-07-01 19:03:58 +04:00
|
|
|
sc->sc_xc_state = NULL;
|
|
|
|
sc->sc_rc_state = NULL;
|
1995-07-04 10:28:17 +04:00
|
|
|
#endif /* PPP_COMPRESS */
|
2014-07-01 19:03:58 +04:00
|
|
|
for (i = 0; i < NUM_NP; ++i)
|
|
|
|
sc->sc_npmode[i] = NPMODE_ERROR;
|
|
|
|
sc->sc_npqueue = NULL;
|
|
|
|
sc->sc_npqtail = &sc->sc_npqueue;
|
|
|
|
sc->sc_last_sent = sc->sc_last_recv = time_second;
|
1994-05-08 16:33:49 +04:00
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
return sc;
|
1994-05-08 16:33:49 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1995-07-04 10:28:17 +04:00
|
|
|
* Deallocate a ppp unit. Must be called at splsoftnet or higher.
|
1994-05-08 16:33:49 +04:00
|
|
|
*/
|
1995-07-04 10:28:17 +04:00
|
|
|
void
|
2005-12-12 02:05:24 +03:00
|
|
|
pppdealloc(struct ppp_softc *sc)
|
1994-05-08 16:33:49 +04:00
|
|
|
{
|
2014-07-01 19:03:58 +04:00
|
|
|
struct mbuf *m;
|
|
|
|
|
|
|
|
softint_disestablish(sc->sc_si);
|
|
|
|
if_down(&sc->sc_if);
|
|
|
|
sc->sc_if.if_flags &= ~(IFF_UP|IFF_RUNNING);
|
|
|
|
sc->sc_devp = NULL;
|
|
|
|
sc->sc_xfer = 0;
|
|
|
|
for (;;) {
|
|
|
|
IF_DEQUEUE(&sc->sc_rawq, m);
|
|
|
|
if (m == NULL)
|
|
|
|
break;
|
|
|
|
m_freem(m);
|
|
|
|
}
|
|
|
|
for (;;) {
|
|
|
|
IF_DEQUEUE(&sc->sc_inq, m);
|
|
|
|
if (m == NULL)
|
|
|
|
break;
|
|
|
|
m_freem(m);
|
|
|
|
}
|
|
|
|
for (;;) {
|
|
|
|
IF_DEQUEUE(&sc->sc_fastq, m);
|
|
|
|
if (m == NULL)
|
|
|
|
break;
|
|
|
|
m_freem(m);
|
|
|
|
}
|
|
|
|
while ((m = sc->sc_npqueue) != NULL) {
|
|
|
|
sc->sc_npqueue = m->m_nextpkt;
|
|
|
|
m_freem(m);
|
|
|
|
}
|
|
|
|
if (sc->sc_togo != NULL) {
|
|
|
|
m_freem(sc->sc_togo);
|
|
|
|
sc->sc_togo = NULL;
|
|
|
|
}
|
1995-07-04 10:28:17 +04:00
|
|
|
#ifdef PPP_COMPRESS
|
2014-07-01 19:03:58 +04:00
|
|
|
ppp_ccp_closed(sc);
|
|
|
|
sc->sc_xc_state = NULL;
|
|
|
|
sc->sc_rc_state = NULL;
|
1995-07-04 10:28:17 +04:00
|
|
|
#endif /* PPP_COMPRESS */
|
1997-03-12 23:26:46 +03:00
|
|
|
#ifdef PPP_FILTER
|
2014-07-01 19:03:58 +04:00
|
|
|
if (sc->sc_pass_filt_in.bf_insns != 0) {
|
|
|
|
free(sc->sc_pass_filt_in.bf_insns, M_DEVBUF);
|
|
|
|
sc->sc_pass_filt_in.bf_insns = 0;
|
|
|
|
sc->sc_pass_filt_in.bf_len = 0;
|
|
|
|
}
|
|
|
|
if (sc->sc_pass_filt_out.bf_insns != 0) {
|
|
|
|
free(sc->sc_pass_filt_out.bf_insns, M_DEVBUF);
|
|
|
|
sc->sc_pass_filt_out.bf_insns = 0;
|
|
|
|
sc->sc_pass_filt_out.bf_len = 0;
|
|
|
|
}
|
|
|
|
if (sc->sc_active_filt_in.bf_insns != 0) {
|
|
|
|
free(sc->sc_active_filt_in.bf_insns, M_DEVBUF);
|
|
|
|
sc->sc_active_filt_in.bf_insns = 0;
|
|
|
|
sc->sc_active_filt_in.bf_len = 0;
|
|
|
|
}
|
|
|
|
if (sc->sc_active_filt_out.bf_insns != 0) {
|
|
|
|
free(sc->sc_active_filt_out.bf_insns, M_DEVBUF);
|
|
|
|
sc->sc_active_filt_out.bf_insns = 0;
|
|
|
|
sc->sc_active_filt_out.bf_len = 0;
|
|
|
|
}
|
1997-03-12 23:26:46 +03:00
|
|
|
#endif /* PPP_FILTER */
|
1996-03-15 05:28:00 +03:00
|
|
|
#ifdef VJC
|
2014-07-01 19:03:58 +04:00
|
|
|
if (sc->sc_comp != 0) {
|
|
|
|
free(sc->sc_comp, M_DEVBUF);
|
|
|
|
sc->sc_comp = 0;
|
|
|
|
}
|
1996-03-15 05:28:00 +03:00
|
|
|
#endif
|
2014-07-01 19:03:58 +04:00
|
|
|
(void)ppp_clone_destroy(&sc->sc_if);
|
1993-08-14 10:29:28 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1995-07-04 10:28:17 +04:00
|
|
|
* Ioctl routine for generic ppp devices.
|
1993-08-14 10:29:28 +04:00
|
|
|
*/
|
|
|
|
int
|
2007-03-04 08:59:00 +03:00
|
|
|
pppioctl(struct ppp_softc *sc, u_long cmd, void *data, int flag,
|
2006-10-12 05:30:41 +04:00
|
|
|
struct lwp *l)
|
1993-08-14 10:29:28 +04:00
|
|
|
{
|
2014-07-01 19:03:58 +04:00
|
|
|
int s, error, flags, mru, npx;
|
|
|
|
u_int nb;
|
|
|
|
struct ppp_option_data *odp;
|
|
|
|
struct compressor *cp;
|
|
|
|
struct npioctl *npi;
|
|
|
|
time_t t;
|
1997-03-12 23:26:46 +03:00
|
|
|
#ifdef PPP_FILTER
|
2014-07-01 19:03:58 +04:00
|
|
|
struct bpf_program *bp, *nbp;
|
|
|
|
struct bpf_insn *newcode, *oldcode;
|
|
|
|
int newcodelen;
|
1997-03-12 23:26:46 +03:00
|
|
|
#endif /* PPP_FILTER */
|
1995-07-04 10:28:17 +04:00
|
|
|
#ifdef PPP_COMPRESS
|
2014-07-01 19:03:58 +04:00
|
|
|
u_char ccp_option[CCP_MAX_OPTION_LENGTH];
|
1995-07-04 10:28:17 +04:00
|
|
|
#endif
|
1994-05-08 16:33:49 +04:00
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
switch (cmd) {
|
|
|
|
case PPPIOCSFLAGS:
|
|
|
|
case PPPIOCSMRU:
|
|
|
|
case PPPIOCSMAXCID:
|
|
|
|
case PPPIOCSCOMPRESS:
|
|
|
|
case PPPIOCSNPMODE:
|
|
|
|
if (kauth_authorize_network(l->l_cred, KAUTH_NETWORK_INTERFACE,
|
|
|
|
KAUTH_REQ_NETWORK_INTERFACE_SETPRIV, &sc->sc_if,
|
|
|
|
KAUTH_ARG(cmd), NULL) != 0)
|
2022-07-06 11:06:59 +03:00
|
|
|
return EPERM;
|
2014-07-01 19:03:58 +04:00
|
|
|
break;
|
|
|
|
case PPPIOCXFERUNIT:
|
|
|
|
/* XXX: Why is this privileged?! */
|
|
|
|
if (kauth_authorize_network(l->l_cred, KAUTH_NETWORK_INTERFACE,
|
|
|
|
KAUTH_REQ_NETWORK_INTERFACE_GETPRIV, &sc->sc_if,
|
|
|
|
KAUTH_ARG(cmd), NULL) != 0)
|
2022-07-06 11:06:59 +03:00
|
|
|
return EPERM;
|
2014-07-01 19:03:58 +04:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2006-07-24 02:06:03 +04:00
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
switch (cmd) {
|
|
|
|
case FIONREAD:
|
|
|
|
*(int *)data = sc->sc_inq.ifq_len;
|
|
|
|
break;
|
1993-08-14 10:29:28 +04:00
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
case PPPIOCGUNIT:
|
|
|
|
*(int *)data = sc->sc_unit;
|
|
|
|
break;
|
1993-08-14 10:29:28 +04:00
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
case PPPIOCGFLAGS:
|
|
|
|
*(u_int *)data = sc->sc_flags;
|
|
|
|
break;
|
1993-08-14 10:29:28 +04:00
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
case PPPIOCGRAWIN:
|
2003-09-01 20:51:25 +04:00
|
|
|
{
|
2014-07-01 19:03:58 +04:00
|
|
|
struct ppp_rawin *rwin = (struct ppp_rawin *)data;
|
|
|
|
u_char c, q = 0;
|
2003-09-01 20:51:25 +04:00
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
for (c = sc->sc_rawin_start; c < sizeof(sc->sc_rawin.buf);)
|
|
|
|
rwin->buf[q++] = sc->sc_rawin.buf[c++];
|
2003-09-01 20:51:25 +04:00
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
for (c = 0; c < sc->sc_rawin_start;)
|
|
|
|
rwin->buf[q++] = sc->sc_rawin.buf[c++];
|
2003-09-01 20:51:25 +04:00
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
rwin->count = sc->sc_rawin.count;
|
2003-09-01 20:51:25 +04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
case PPPIOCSFLAGS:
|
|
|
|
flags = *(int *)data & SC_MASK;
|
|
|
|
s = splsoftnet();
|
1995-07-04 10:28:17 +04:00
|
|
|
#ifdef PPP_COMPRESS
|
2014-07-01 19:03:58 +04:00
|
|
|
if (sc->sc_flags & SC_CCP_OPEN && !(flags & SC_CCP_OPEN))
|
|
|
|
ppp_ccp_closed(sc);
|
1995-07-04 10:28:17 +04:00
|
|
|
#endif
|
2014-07-01 19:03:58 +04:00
|
|
|
splhigh(); /* XXX IMP ME HARDER */
|
|
|
|
sc->sc_flags = (sc->sc_flags & ~SC_MASK) | flags;
|
|
|
|
splx(s);
|
|
|
|
break;
|
1993-08-14 10:29:28 +04:00
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
case PPPIOCSMRU:
|
|
|
|
mru = *(int *)data;
|
|
|
|
if (mru >= PPP_MINMRU && mru <= PPP_MAXMRU)
|
|
|
|
sc->sc_mru = mru;
|
|
|
|
break;
|
1993-08-31 04:05:27 +04:00
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
case PPPIOCGMRU:
|
|
|
|
*(int *)data = sc->sc_mru;
|
|
|
|
break;
|
1993-08-31 04:05:27 +04:00
|
|
|
|
1994-05-08 16:33:49 +04:00
|
|
|
#ifdef VJC
|
2014-07-01 19:03:58 +04:00
|
|
|
case PPPIOCSMAXCID:
|
|
|
|
if (sc->sc_comp) {
|
|
|
|
s = splsoftnet();
|
|
|
|
sl_compress_setup(sc->sc_comp, *(int *)data);
|
|
|
|
splx(s);
|
|
|
|
}
|
|
|
|
break;
|
1994-05-08 16:33:49 +04:00
|
|
|
#endif
|
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
case PPPIOCXFERUNIT:
|
|
|
|
sc->sc_xfer = l->l_proc->p_pid;
|
|
|
|
break;
|
1994-05-08 16:33:49 +04:00
|
|
|
|
1995-07-04 10:28:17 +04:00
|
|
|
#ifdef PPP_COMPRESS
|
2014-07-01 19:03:58 +04:00
|
|
|
case PPPIOCSCOMPRESS:
|
2022-07-06 11:06:59 +03:00
|
|
|
odp = (struct ppp_option_data *)data;
|
2014-07-01 19:03:58 +04:00
|
|
|
nb = odp->length;
|
|
|
|
if (nb > sizeof(ccp_option))
|
|
|
|
nb = sizeof(ccp_option);
|
2022-07-06 11:07:23 +03:00
|
|
|
if (nb < 3)
|
|
|
|
return EINVAL;
|
2014-07-01 19:03:58 +04:00
|
|
|
if ((error = copyin(odp->ptr, ccp_option, nb)) != 0)
|
2022-07-06 11:06:59 +03:00
|
|
|
return error;
|
2014-07-01 19:03:58 +04:00
|
|
|
/* preliminary check on the length byte */
|
|
|
|
if (ccp_option[1] < 2)
|
2022-07-06 11:06:59 +03:00
|
|
|
return EINVAL;
|
2014-07-01 19:03:58 +04:00
|
|
|
cp = ppp_get_compressor(ccp_option[0]);
|
|
|
|
if (cp == NULL) {
|
|
|
|
if (sc->sc_flags & SC_DEBUG)
|
|
|
|
printf("%s: no compressor for [%x %x %x], %x\n",
|
|
|
|
sc->sc_if.if_xname, ccp_option[0],
|
|
|
|
ccp_option[1], ccp_option[2], nb);
|
2022-07-06 11:06:59 +03:00
|
|
|
return EINVAL; /* no handler found */
|
2014-07-01 19:03:58 +04:00
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Found a handler for the protocol - try to allocate
|
|
|
|
* a compressor or decompressor.
|
|
|
|
*/
|
|
|
|
error = 0;
|
|
|
|
if (odp->transmit) {
|
|
|
|
s = splsoftnet();
|
|
|
|
if (sc->sc_xc_state != NULL) {
|
|
|
|
(*sc->sc_xcomp->comp_free)(sc->sc_xc_state);
|
|
|
|
ppp_compressor_rele(sc->sc_xcomp);
|
|
|
|
}
|
|
|
|
sc->sc_xcomp = cp;
|
|
|
|
sc->sc_xc_state = cp->comp_alloc(ccp_option, nb);
|
|
|
|
if (sc->sc_xc_state == NULL) {
|
|
|
|
if (sc->sc_flags & SC_DEBUG)
|
|
|
|
printf("%s: comp_alloc failed\n",
|
|
|
|
sc->sc_if.if_xname);
|
|
|
|
error = ENOBUFS;
|
|
|
|
}
|
|
|
|
splhigh(); /* XXX IMP ME HARDER */
|
|
|
|
sc->sc_flags &= ~SC_COMP_RUN;
|
|
|
|
splx(s);
|
|
|
|
} else {
|
|
|
|
s = splsoftnet();
|
|
|
|
if (sc->sc_rc_state != NULL) {
|
|
|
|
(*sc->sc_rcomp->decomp_free)(sc->sc_rc_state);
|
|
|
|
ppp_compressor_rele(sc->sc_rcomp);
|
|
|
|
}
|
|
|
|
sc->sc_rcomp = cp;
|
|
|
|
sc->sc_rc_state = cp->decomp_alloc(ccp_option, nb);
|
|
|
|
if (sc->sc_rc_state == NULL) {
|
|
|
|
if (sc->sc_flags & SC_DEBUG)
|
|
|
|
printf("%s: decomp_alloc failed\n",
|
|
|
|
sc->sc_if.if_xname);
|
|
|
|
error = ENOBUFS;
|
|
|
|
}
|
|
|
|
splhigh(); /* XXX IMP ME HARDER */
|
|
|
|
sc->sc_flags &= ~SC_DECOMP_RUN;
|
|
|
|
splx(s);
|
|
|
|
}
|
2022-07-06 11:06:59 +03:00
|
|
|
return error;
|
1995-07-04 10:28:17 +04:00
|
|
|
#endif /* PPP_COMPRESS */
|
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
case PPPIOCGNPMODE:
|
|
|
|
case PPPIOCSNPMODE:
|
2022-07-06 11:06:59 +03:00
|
|
|
npi = (struct npioctl *)data;
|
2014-07-01 19:03:58 +04:00
|
|
|
switch (npi->protocol) {
|
|
|
|
case PPP_IP:
|
|
|
|
npx = NP_IP;
|
|
|
|
break;
|
|
|
|
case PPP_IPV6:
|
|
|
|
npx = NP_IPV6;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return EINVAL;
|
1995-07-04 10:28:17 +04:00
|
|
|
}
|
2014-07-01 19:03:58 +04:00
|
|
|
if (cmd == PPPIOCGNPMODE) {
|
|
|
|
npi->mode = sc->sc_npmode[npx];
|
|
|
|
} else {
|
|
|
|
if (npi->mode != sc->sc_npmode[npx]) {
|
|
|
|
s = splnet();
|
|
|
|
sc->sc_npmode[npx] = npi->mode;
|
|
|
|
if (npi->mode != NPMODE_QUEUE) {
|
|
|
|
ppp_requeue(sc);
|
|
|
|
ppp_restart(sc);
|
|
|
|
}
|
|
|
|
splx(s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
1995-07-04 10:28:17 +04:00
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
case PPPIOCGIDLE:
|
|
|
|
s = splsoftnet();
|
|
|
|
t = time_second;
|
|
|
|
((struct ppp_idle *)data)->xmit_idle = t - sc->sc_last_sent;
|
|
|
|
((struct ppp_idle *)data)->recv_idle = t - sc->sc_last_recv;
|
|
|
|
splx(s);
|
|
|
|
break;
|
1995-07-04 10:28:17 +04:00
|
|
|
|
1997-03-12 23:26:46 +03:00
|
|
|
#ifdef PPP_FILTER
|
2014-07-01 19:03:58 +04:00
|
|
|
case PPPIOCSPASS:
|
|
|
|
case PPPIOCSACTIVE:
|
|
|
|
/* These are no longer supported. */
|
|
|
|
return EOPNOTSUPP;
|
Decouple inbound and outbound filters. Now instead of using "active-filter"
and "pass-filter" and "inbound" and "outbound" qualifiers in the filter
expression, use new "active-filter-in", "active-filter-out", "pass-filter-in",
and "pass-filter-out" without these qualifiers.
This is necessary due to the horrible, awful way "inbound" and "outbound"
were specified for the filter programs when a packet was passed through them.
Basically, the "address" byte in the serial PPP header was overwritten with
a value to indicate the direction. However, the "address" byte doesn't even
exist on PPP headers for all other PPP encaps! So, this old method worked
only for serial encaps, and corrupted packets for all others (PPPoE, ATM, etc.)
1999-05-12 22:50:51 +04:00
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
case PPPIOCSIPASS:
|
Decouple inbound and outbound filters. Now instead of using "active-filter"
and "pass-filter" and "inbound" and "outbound" qualifiers in the filter
expression, use new "active-filter-in", "active-filter-out", "pass-filter-in",
and "pass-filter-out" without these qualifiers.
This is necessary due to the horrible, awful way "inbound" and "outbound"
were specified for the filter programs when a packet was passed through them.
Basically, the "address" byte in the serial PPP header was overwritten with
a value to indicate the direction. However, the "address" byte doesn't even
exist on PPP headers for all other PPP encaps! So, this old method worked
only for serial encaps, and corrupted packets for all others (PPPoE, ATM, etc.)
1999-05-12 22:50:51 +04:00
|
|
|
case PPPIOCSOPASS:
|
|
|
|
case PPPIOCSIACTIVE:
|
|
|
|
case PPPIOCSOACTIVE:
|
2022-07-06 11:06:59 +03:00
|
|
|
nbp = (struct bpf_program *)data;
|
2014-07-01 19:03:58 +04:00
|
|
|
if ((unsigned) nbp->bf_len > BPF_MAXINSNS)
|
|
|
|
return EINVAL;
|
|
|
|
newcodelen = nbp->bf_len * sizeof(struct bpf_insn);
|
|
|
|
if (newcodelen != 0) {
|
|
|
|
newcode = malloc(newcodelen, M_DEVBUF, M_WAITOK);
|
|
|
|
/* WAITOK -- malloc() never fails. */
|
|
|
|
if ((error = copyin((void *)nbp->bf_insns,
|
|
|
|
(void *)newcode, newcodelen)) != 0) {
|
|
|
|
free(newcode, M_DEVBUF);
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
if (!bpf_validate(newcode, nbp->bf_len)) {
|
|
|
|
free(newcode, M_DEVBUF);
|
|
|
|
return EINVAL;
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
newcode = 0;
|
|
|
|
switch (cmd) {
|
|
|
|
case PPPIOCSIPASS:
|
|
|
|
bp = &sc->sc_pass_filt_in;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PPPIOCSOPASS:
|
|
|
|
bp = &sc->sc_pass_filt_out;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PPPIOCSIACTIVE:
|
|
|
|
bp = &sc->sc_active_filt_in;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PPPIOCSOACTIVE:
|
|
|
|
bp = &sc->sc_active_filt_out;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
free(newcode, M_DEVBUF);
|
2022-07-06 11:06:59 +03:00
|
|
|
return EPASSTHROUGH;
|
2014-07-01 19:03:58 +04:00
|
|
|
}
|
|
|
|
oldcode = bp->bf_insns;
|
|
|
|
s = splnet();
|
|
|
|
bp->bf_len = nbp->bf_len;
|
|
|
|
bp->bf_insns = newcode;
|
|
|
|
splx(s);
|
|
|
|
if (oldcode != 0)
|
|
|
|
free(oldcode, M_DEVBUF);
|
|
|
|
break;
|
Decouple inbound and outbound filters. Now instead of using "active-filter"
and "pass-filter" and "inbound" and "outbound" qualifiers in the filter
expression, use new "active-filter-in", "active-filter-out", "pass-filter-in",
and "pass-filter-out" without these qualifiers.
This is necessary due to the horrible, awful way "inbound" and "outbound"
were specified for the filter programs when a packet was passed through them.
Basically, the "address" byte in the serial PPP header was overwritten with
a value to indicate the direction. However, the "address" byte doesn't even
exist on PPP headers for all other PPP encaps! So, this old method worked
only for serial encaps, and corrupted packets for all others (PPPoE, ATM, etc.)
1999-05-12 22:50:51 +04:00
|
|
|
#endif /* PPP_FILTER */
|
1996-03-15 05:28:00 +03:00
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
default:
|
2022-07-06 11:06:59 +03:00
|
|
|
return EPASSTHROUGH;
|
2014-07-01 19:03:58 +04:00
|
|
|
}
|
2022-07-06 11:06:59 +03:00
|
|
|
return 0;
|
1993-08-14 10:29:28 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1995-07-04 10:28:17 +04:00
|
|
|
* Process an ioctl request to the ppp network interface.
|
1993-08-14 10:29:28 +04:00
|
|
|
*/
|
1997-03-12 23:26:46 +03:00
|
|
|
static int
|
2007-03-04 08:59:00 +03:00
|
|
|
pppsioctl(struct ifnet *ifp, u_long cmd, void *data)
|
1993-08-14 10:29:28 +04:00
|
|
|
{
|
2014-07-01 19:03:58 +04:00
|
|
|
struct ppp_softc *sc = ifp->if_softc;
|
|
|
|
struct ifaddr *ifa = (struct ifaddr *)data;
|
|
|
|
struct ifreq *ifr = (struct ifreq *)data;
|
|
|
|
struct ppp_stats *psp;
|
1995-07-04 10:28:17 +04:00
|
|
|
#ifdef PPP_COMPRESS
|
2014-07-01 19:03:58 +04:00
|
|
|
struct ppp_comp_stats *pcp;
|
1995-07-04 10:28:17 +04:00
|
|
|
#endif
|
2014-07-01 19:03:58 +04:00
|
|
|
int s = splnet(), error = 0;
|
1995-07-04 10:28:17 +04:00
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
switch (cmd) {
|
|
|
|
case SIOCSIFFLAGS:
|
|
|
|
if ((error = ifioctl_common(ifp, cmd, data)) != 0)
|
|
|
|
break;
|
|
|
|
if ((ifp->if_flags & IFF_RUNNING) == 0)
|
|
|
|
ifp->if_flags &= ~IFF_UP;
|
*** Summary ***
When a link-layer address changes (e.g., ifconfig ex0 link
02:de:ad:be:ef:02 active), send a gratuitous ARP and/or a Neighbor
Advertisement to update the network-/link-layer address bindings
on our LAN peers.
Refuse a change of ethernet address to the address 00:00:00:00:00:00
or to any multicast/broadcast address. (Thanks matt@.)
Reorder ifnet ioctl operations so that driver ioctls may inherit
the functions of their "class"---ether_ioctl(), fddi_ioctl(), et
cetera---and the class ioctls may inherit from the generic ioctl,
ifioctl_common(), but both driver- and class-ioctls may override
the generic behavior. Make network drivers share more code.
Distinguish a "factory" link-layer address from others for the
purposes of both protecting that address from deletion and computing
EUI64.
Return consistent, appropriate error codes from network drivers.
Improve readability. KNF.
*** Details ***
In if_attach(), always initialize the interface ioctl routine,
ifnet->if_ioctl, if the driver has not already initialized it.
Delete if_ioctl == NULL tests everywhere else, because it cannot
happen.
In the ioctl routines of network interfaces, inherit common ioctl
behaviors by calling either ifioctl_common() or whichever ioctl
routine is appropriate for the class of interface---e.g., ether_ioctl()
for ethernets.
Stop (ab)using SIOCSIFADDR and start to use SIOCINITIFADDR. In
the user->kernel interface, SIOCSIFADDR's argument was an ifreq,
but on the protocol->ifnet interface, SIOCSIFADDR's argument was
an ifaddr. That was confusing, and it would work against me as I
make it possible for a network interface to overload most ioctls.
On the protocol->ifnet interface, replace SIOCSIFADDR with
SIOCINITIFADDR. In ifioctl(), return EPERM if userland tries to
invoke SIOCINITIFADDR.
In ifioctl(), give the interface the first shot at handling most
interface ioctls, and give the protocol the second shot, instead
of the other way around. Finally, let compatibility code (COMPAT_OSOCK)
take a shot.
Pull device initialization out of switch statements under
SIOCINITIFADDR. For example, pull ..._init() out of any switch
statement that looks like this:
switch (...->sa_family) {
case ...:
..._init();
...
break;
...
default:
..._init();
...
break;
}
Rewrite many if-else clauses that handle all permutations of IFF_UP
and IFF_RUNNING to use a switch statement,
switch (x & (IFF_UP|IFF_RUNNING)) {
case 0:
...
break;
case IFF_RUNNING:
...
break;
case IFF_UP:
...
break;
case IFF_UP|IFF_RUNNING:
...
break;
}
unifdef lots of code containing #ifdef FreeBSD, #ifdef NetBSD, and
#ifdef SIOCSIFMTU, especially in fwip(4) and in ndis(4).
In ipw(4), remove an if_set_sadl() call that is out of place.
In nfe(4), reuse the jumbo MTU logic in ether_ioctl().
Let ethernets register a callback for setting h/w state such as
promiscuous mode and the multicast filter in accord with a change
in the if_flags: ether_set_ifflags_cb() registers a callback that
returns ENETRESET if the caller should reset the ethernet by calling
if_init(), 0 on success, != 0 on failure. Pull common code from
ex(4), gem(4), nfe(4), sip(4), tlp(4), vge(4) into ether_ioctl(),
and register if_flags callbacks for those drivers.
Return ENOTTY instead of EINVAL for inappropriate ioctls. In
zyd(4), use ENXIO instead of ENOTTY to indicate that the device is
not any longer attached.
Add to if_set_sadl() a boolean 'factory' argument that indicates
whether a link-layer address was assigned by the factory or some
other source. In a comment, recommend using the factory address
for generating an EUI64, and update in6_get_hw_ifid() to prefer a
factory address to any other link-layer address.
Add a routing message, RTM_LLINFO_UPD, that tells protocols to
update the binding of network-layer addresses to link-layer addresses.
Implement this message in IPv4 and IPv6 by sending a gratuitous
ARP or a neighbor advertisement, respectively. Generate RTM_LLINFO_UPD
messages on a change of an interface's link-layer address.
In ether_ioctl(), do not let SIOCALIFADDR set a link-layer address
that is broadcast/multicast or equal to 00:00:00:00:00:00.
Make ether_ioctl() call ifioctl_common() to handle ioctls that it
does not understand.
In gif(4), initialize if_softc and use it, instead of assuming that
the gif_softc and ifp overlap.
Let ifioctl_common() handle SIOCGIFADDR.
Sprinkle rtcache_invariants(), which checks on DIAGNOSTIC kernels
that certain invariants on a struct route are satisfied.
In agr(4), rewrite agr_ioctl_filter() to be a bit more explicit
about the ioctls that we do not allow on an agr(4) member interface.
bzero -> memset. Delete unnecessary casts to void *. Use
sockaddr_in_init() and sockaddr_in6_init(). Compare pointers with
NULL instead of "testing truth". Replace some instances of (type
*)0 with NULL. Change some K&R prototypes to ANSI C, and join
lines.
2008-11-07 03:20:01 +03:00
|
|
|
break;
|
1995-07-04 10:28:17 +04:00
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
case SIOCINITIFADDR:
|
|
|
|
switch (ifa->ifa_addr->sa_family) {
|
1999-07-30 14:35:34 +04:00
|
|
|
#ifdef INET
|
2014-07-01 19:03:58 +04:00
|
|
|
case AF_INET:
|
|
|
|
break;
|
1999-07-30 14:35:34 +04:00
|
|
|
#endif
|
|
|
|
#ifdef INET6
|
2014-07-01 19:03:58 +04:00
|
|
|
case AF_INET6:
|
|
|
|
break;
|
1999-07-30 14:35:34 +04:00
|
|
|
#endif
|
2014-07-01 19:03:58 +04:00
|
|
|
default:
|
2017-09-17 23:39:04 +03:00
|
|
|
printf("%s: af%d not supported\n", ifp->if_xname,
|
|
|
|
ifa->ifa_addr->sa_family);
|
2014-07-01 19:03:58 +04:00
|
|
|
error = EAFNOSUPPORT;
|
|
|
|
break;
|
|
|
|
}
|
2015-04-20 13:19:54 +03:00
|
|
|
ifa->ifa_rtrequest = p2p_rtrequest;
|
2014-07-01 19:03:58 +04:00
|
|
|
break;
|
1995-07-04 10:28:17 +04:00
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
case SIOCADDMULTI:
|
|
|
|
case SIOCDELMULTI:
|
|
|
|
if (ifr == NULL) {
|
|
|
|
error = EAFNOSUPPORT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
switch (ifreq_getaddr(cmd, ifr)->sa_family) {
|
1996-03-15 05:28:00 +03:00
|
|
|
#ifdef INET
|
2014-07-01 19:03:58 +04:00
|
|
|
case AF_INET:
|
|
|
|
break;
|
1999-07-30 14:35:34 +04:00
|
|
|
#endif
|
|
|
|
#ifdef INET6
|
2014-07-01 19:03:58 +04:00
|
|
|
case AF_INET6:
|
|
|
|
break;
|
1996-03-15 05:28:00 +03:00
|
|
|
#endif
|
2014-07-01 19:03:58 +04:00
|
|
|
default:
|
|
|
|
error = EAFNOSUPPORT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
1996-03-15 05:28:00 +03:00
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
case SIOCGPPPSTATS:
|
2022-07-06 11:06:59 +03:00
|
|
|
psp = &((struct ifpppstatsreq *)data)->stats;
|
2014-07-01 19:03:58 +04:00
|
|
|
memset(psp, 0, sizeof(*psp));
|
|
|
|
psp->p = sc->sc_stats;
|
1996-03-15 05:28:00 +03:00
|
|
|
#if defined(VJC) && !defined(SL_NO_STATS)
|
2014-07-01 19:03:58 +04:00
|
|
|
if (sc->sc_comp) {
|
|
|
|
psp->vj.vjs_packets = sc->sc_comp->sls_packets;
|
|
|
|
psp->vj.vjs_compressed = sc->sc_comp->sls_compressed;
|
|
|
|
psp->vj.vjs_searches = sc->sc_comp->sls_searches;
|
|
|
|
psp->vj.vjs_misses = sc->sc_comp->sls_misses;
|
|
|
|
psp->vj.vjs_uncompressedin = sc->sc_comp->sls_uncompressedin;
|
|
|
|
psp->vj.vjs_compressedin = sc->sc_comp->sls_compressedin;
|
|
|
|
psp->vj.vjs_errorin = sc->sc_comp->sls_errorin;
|
|
|
|
psp->vj.vjs_tossed = sc->sc_comp->sls_tossed;
|
|
|
|
}
|
1995-07-04 10:28:17 +04:00
|
|
|
#endif /* VJC */
|
2014-07-01 19:03:58 +04:00
|
|
|
break;
|
1995-07-04 10:28:17 +04:00
|
|
|
|
|
|
|
#ifdef PPP_COMPRESS
|
2014-07-01 19:03:58 +04:00
|
|
|
case SIOCGPPPCSTATS:
|
2022-07-06 11:06:59 +03:00
|
|
|
pcp = &((struct ifpppcstatsreq *)data)->stats;
|
2014-07-01 19:03:58 +04:00
|
|
|
memset(pcp, 0, sizeof(*pcp));
|
|
|
|
if (sc->sc_xc_state != NULL)
|
|
|
|
(*sc->sc_xcomp->comp_stat)(sc->sc_xc_state, &pcp->c);
|
|
|
|
if (sc->sc_rc_state != NULL)
|
|
|
|
(*sc->sc_rcomp->decomp_stat)(sc->sc_rc_state, &pcp->d);
|
|
|
|
break;
|
1995-07-04 10:28:17 +04:00
|
|
|
#endif /* PPP_COMPRESS */
|
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
default:
|
|
|
|
if ((error = ifioctl_common(&sc->sc_if, cmd, data)) == ENETRESET)
|
|
|
|
error = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
splx(s);
|
2022-07-06 11:06:59 +03:00
|
|
|
return error;
|
1993-08-14 10:29:28 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Queue a packet. Start transmission if not active.
|
|
|
|
* Packet is placed in Information field of PPP frame.
|
|
|
|
*/
|
|
|
|
int
|
KNF: de-__P, bzero -> memset, bcmp -> memcmp. Remove extraneous
parentheses in return statements.
Cosmetic: don't open-code TAILQ_FOREACH().
Cosmetic: change types of variables to avoid oodles of casts: in
in6_src.c, avoid casts by changing several route_in6 pointers
to struct route pointers. Remove unnecessary casts to caddr_t
elsewhere.
Pave the way for eliminating address family-specific route caches:
soon, struct route will not embed a sockaddr, but it will hold
a reference to an external sockaddr, instead. We will set the
destination sockaddr using rtcache_setdst(). (I created a stub
for it, but it isn't used anywhere, yet.) rtcache_free() will
free the sockaddr. I have extracted from rtcache_free() a helper
subroutine, rtcache_clear(). rtcache_clear() will "forget" a
cached route, but it will not forget the destination by releasing
the sockaddr. I use rtcache_clear() instead of rtcache_free()
in rtcache_update(), because rtcache_update() is not supposed
to forget the destination.
Constify:
1 Introduce const accessor for route->ro_dst, rtcache_getdst().
2 Constify the 'dst' argument to ifnet->if_output(). This
led me to constify a lot of code called by output routines.
3 Constify the sockaddr argument to protosw->pr_ctlinput. This
led me to constify a lot of code called by ctlinput routines.
4 Introduce const macros for converting from a generic sockaddr
to family-specific sockaddrs, e.g., sockaddr_in: satocsin6,
satocsin, et cetera.
2007-02-18 01:34:07 +03:00
|
|
|
pppoutput(struct ifnet *ifp, struct mbuf *m0, const struct sockaddr *dst,
|
2016-04-28 03:16:56 +03:00
|
|
|
const struct rtentry *rtp)
|
1993-08-14 10:29:28 +04:00
|
|
|
{
|
2014-07-01 19:03:58 +04:00
|
|
|
struct ppp_softc *sc = ifp->if_softc;
|
|
|
|
int protocol, address, control;
|
|
|
|
u_char *cp;
|
|
|
|
int s, error;
|
2000-10-02 07:54:10 +04:00
|
|
|
#ifdef INET
|
2014-07-01 19:03:58 +04:00
|
|
|
struct ip *ip;
|
2000-10-02 07:54:10 +04:00
|
|
|
#endif
|
2014-07-01 19:03:58 +04:00
|
|
|
struct ifqueue *ifq;
|
|
|
|
enum NPmode mode;
|
|
|
|
int len;
|
|
|
|
|
2022-07-06 11:06:59 +03:00
|
|
|
if (sc->sc_devp == NULL ||
|
|
|
|
(ifp->if_flags & IFF_RUNNING) == 0 ||
|
|
|
|
((ifp->if_flags & IFF_UP) == 0 &&
|
|
|
|
dst->sa_family != AF_UNSPEC)) {
|
2014-07-01 19:03:58 +04:00
|
|
|
error = ENETDOWN; /* sort of */
|
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
|
2016-04-20 12:01:03 +03:00
|
|
|
IFQ_CLASSIFY(&ifp->if_snd, m0, dst->sa_family);
|
1995-07-04 10:28:17 +04:00
|
|
|
|
1993-08-31 04:05:27 +04:00
|
|
|
/*
|
2014-07-01 19:03:58 +04:00
|
|
|
* Compute PPP header.
|
1993-08-31 04:05:27 +04:00
|
|
|
*/
|
2014-07-01 19:03:58 +04:00
|
|
|
m0->m_flags &= ~M_HIGHPRI;
|
|
|
|
switch (dst->sa_family) {
|
|
|
|
#ifdef INET
|
|
|
|
case AF_INET:
|
|
|
|
address = PPP_ALLSTATIONS;
|
|
|
|
control = PPP_UI;
|
|
|
|
protocol = PPP_IP;
|
|
|
|
mode = sc->sc_npmode[NP_IP];
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If this packet has the "low delay" bit set in the IP header,
|
|
|
|
* put it on the fastq instead.
|
|
|
|
*/
|
|
|
|
ip = mtod(m0, struct ip *);
|
|
|
|
if (ip->ip_tos & IPTOS_LOWDELAY)
|
|
|
|
m0->m_flags |= M_HIGHPRI;
|
|
|
|
break;
|
1999-07-30 14:35:34 +04:00
|
|
|
#endif
|
|
|
|
#ifdef INET6
|
2014-07-01 19:03:58 +04:00
|
|
|
case AF_INET6:
|
|
|
|
address = PPP_ALLSTATIONS; /*XXX*/
|
|
|
|
control = PPP_UI; /*XXX*/
|
|
|
|
protocol = PPP_IPV6;
|
|
|
|
mode = sc->sc_npmode[NP_IPV6];
|
1999-07-30 14:35:34 +04:00
|
|
|
|
|
|
|
#if 0 /* XXX flowinfo/traffic class, maybe? */
|
|
|
|
/*
|
|
|
|
* If this packet has the "low delay" bit set in the IP header,
|
|
|
|
* put it on the fastq instead.
|
|
|
|
*/
|
2014-07-01 19:03:58 +04:00
|
|
|
ip = mtod(m0, struct ip *);
|
|
|
|
if (ip->ip_tos & IPTOS_LOWDELAY)
|
|
|
|
m0->m_flags |= M_HIGHPRI;
|
1999-07-30 14:35:34 +04:00
|
|
|
#endif
|
2014-07-01 19:03:58 +04:00
|
|
|
break;
|
1993-08-14 10:29:28 +04:00
|
|
|
#endif
|
2014-07-01 19:03:58 +04:00
|
|
|
case AF_UNSPEC:
|
|
|
|
address = PPP_ADDRESS(dst->sa_data);
|
|
|
|
control = PPP_CONTROL(dst->sa_data);
|
|
|
|
protocol = PPP_PROTOCOL(dst->sa_data);
|
|
|
|
mode = NPMODE_PASS;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
printf("%s: af%d not supported\n", ifp->if_xname,
|
|
|
|
dst->sa_family);
|
|
|
|
error = EAFNOSUPPORT;
|
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
|
1997-03-12 23:26:46 +03:00
|
|
|
/*
|
2014-07-01 19:03:58 +04:00
|
|
|
* Drop this packet, or return an error, if necessary.
|
1997-03-12 23:26:46 +03:00
|
|
|
*/
|
2014-07-01 19:03:58 +04:00
|
|
|
if (mode == NPMODE_ERROR) {
|
|
|
|
error = ENETDOWN;
|
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
if (mode == NPMODE_DROP) {
|
|
|
|
error = 0;
|
|
|
|
goto bad;
|
1996-03-15 05:28:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2014-07-01 19:03:58 +04:00
|
|
|
* Add PPP header.
|
1996-03-15 05:28:00 +03:00
|
|
|
*/
|
2014-07-01 19:03:58 +04:00
|
|
|
M_PREPEND(m0, PPP_HDRLEN, M_DONTWAIT);
|
|
|
|
if (m0 == NULL) {
|
|
|
|
error = ENOBUFS;
|
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
|
|
|
|
cp = mtod(m0, u_char *);
|
|
|
|
*cp++ = address;
|
|
|
|
*cp++ = control;
|
|
|
|
*cp++ = protocol >> 8;
|
|
|
|
*cp++ = protocol & 0xff;
|
|
|
|
|
|
|
|
len = m_length(m0);
|
|
|
|
|
|
|
|
if (sc->sc_flags & SC_LOG_OUTPKT) {
|
|
|
|
printf("%s output: ", ifp->if_xname);
|
|
|
|
pppdumpm(m0);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((protocol & 0x8000) == 0) {
|
|
|
|
#ifdef PPP_FILTER
|
|
|
|
/*
|
|
|
|
* Apply the pass and active filters to the packet,
|
|
|
|
* but only if it is a data packet.
|
|
|
|
*/
|
2022-07-06 11:06:59 +03:00
|
|
|
if (sc->sc_pass_filt_out.bf_insns != 0 &&
|
|
|
|
bpf_filter(sc->sc_pass_filt_out.bf_insns,
|
2014-07-01 19:03:58 +04:00
|
|
|
(u_char *)m0, len, 0) == 0) {
|
|
|
|
error = 0; /* drop this packet */
|
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Update the time we sent the most recent packet.
|
|
|
|
*/
|
2022-07-06 11:06:59 +03:00
|
|
|
if (sc->sc_active_filt_out.bf_insns == 0 ||
|
|
|
|
bpf_filter(sc->sc_active_filt_out.bf_insns,
|
2014-07-01 19:03:58 +04:00
|
|
|
(u_char *)m0, len, 0))
|
|
|
|
sc->sc_last_sent = time_second;
|
1997-03-12 23:26:46 +03:00
|
|
|
#else
|
2014-07-01 19:03:58 +04:00
|
|
|
/*
|
|
|
|
* Update the time we sent the most recent packet.
|
|
|
|
*/
|
|
|
|
sc->sc_last_sent = time_second;
|
|
|
|
#endif /* PPP_FILTER */
|
|
|
|
}
|
|
|
|
|
1997-03-12 23:26:46 +03:00
|
|
|
/*
|
2014-07-01 19:03:58 +04:00
|
|
|
* See if bpf wants to look at the packet.
|
1997-03-12 23:26:46 +03:00
|
|
|
*/
|
2018-06-26 09:47:57 +03:00
|
|
|
bpf_mtap(&sc->sc_if, m0, BPF_D_OUT);
|
2014-07-01 19:03:58 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Put the packet on the appropriate queue.
|
|
|
|
*/
|
|
|
|
s = splnet();
|
|
|
|
if (mode == NPMODE_QUEUE) {
|
|
|
|
/* XXX we should limit the number of packets on this queue */
|
|
|
|
*sc->sc_npqtail = m0;
|
|
|
|
m0->m_nextpkt = NULL;
|
|
|
|
sc->sc_npqtail = &m0->m_nextpkt;
|
|
|
|
} else {
|
|
|
|
ifq = (m0->m_flags & M_HIGHPRI) ? &sc->sc_fastq : NULL;
|
2016-04-20 12:01:03 +03:00
|
|
|
if ((error = ifq_enqueue2(&sc->sc_if, ifq, m0)) != 0) {
|
2014-07-01 19:03:58 +04:00
|
|
|
splx(s);
|
2020-01-29 07:28:27 +03:00
|
|
|
if_statinc(&sc->sc_if, if_oerrors);
|
2014-07-01 19:03:58 +04:00
|
|
|
sc->sc_stats.ppp_oerrors++;
|
2022-07-06 11:06:59 +03:00
|
|
|
return error;
|
2014-07-01 19:03:58 +04:00
|
|
|
}
|
|
|
|
ppp_restart(sc);
|
1995-07-04 10:28:17 +04:00
|
|
|
}
|
2020-01-29 07:28:27 +03:00
|
|
|
if_statadd2(ifp, if_opackets, 1, if_obytes, len);
|
1994-05-08 16:33:49 +04:00
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
splx(s);
|
2022-07-06 11:06:59 +03:00
|
|
|
return 0;
|
1993-08-14 10:29:28 +04:00
|
|
|
|
|
|
|
bad:
|
2014-07-01 19:03:58 +04:00
|
|
|
m_freem(m0);
|
2022-07-06 11:06:59 +03:00
|
|
|
return error;
|
1993-08-14 10:29:28 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1995-07-04 10:28:17 +04:00
|
|
|
* After a change in the NPmode for some NP, move packets from the
|
|
|
|
* npqueue to the send queue or the fast queue as appropriate.
|
2001-04-14 03:29:55 +04:00
|
|
|
* Should be called at splnet, since we muck with the queues.
|
1994-05-08 16:33:49 +04:00
|
|
|
*/
|
1995-07-04 10:28:17 +04:00
|
|
|
static void
|
2005-12-12 02:05:24 +03:00
|
|
|
ppp_requeue(struct ppp_softc *sc)
|
1994-05-08 16:33:49 +04:00
|
|
|
{
|
2014-07-01 19:03:58 +04:00
|
|
|
struct mbuf *m, **mpp;
|
|
|
|
struct ifqueue *ifq;
|
|
|
|
enum NPmode mode;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
for (mpp = &sc->sc_npqueue; (m = *mpp) != NULL; ) {
|
|
|
|
switch (PPP_PROTOCOL(mtod(m, u_char *))) {
|
|
|
|
case PPP_IP:
|
|
|
|
mode = sc->sc_npmode[NP_IP];
|
|
|
|
break;
|
|
|
|
case PPP_IPV6:
|
|
|
|
mode = sc->sc_npmode[NP_IPV6];
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
mode = NPMODE_PASS;
|
|
|
|
}
|
1994-05-08 16:33:49 +04:00
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
switch (mode) {
|
|
|
|
case NPMODE_PASS:
|
|
|
|
/*
|
|
|
|
* This packet can now go on one of the queues to
|
|
|
|
* be sent.
|
|
|
|
*/
|
|
|
|
*mpp = m->m_nextpkt;
|
|
|
|
m->m_nextpkt = NULL;
|
|
|
|
ifq = (m->m_flags & M_HIGHPRI) ? &sc->sc_fastq : NULL;
|
2016-04-20 12:01:03 +03:00
|
|
|
if ((error = ifq_enqueue2(&sc->sc_if, ifq, m)) != 0) {
|
2020-01-29 07:28:27 +03:00
|
|
|
if_statinc(&sc->sc_if, if_oerrors);
|
2014-07-01 19:03:58 +04:00
|
|
|
sc->sc_stats.ppp_oerrors++;
|
|
|
|
}
|
|
|
|
break;
|
1994-05-08 16:33:49 +04:00
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
case NPMODE_DROP:
|
|
|
|
case NPMODE_ERROR:
|
|
|
|
*mpp = m->m_nextpkt;
|
|
|
|
m_freem(m);
|
|
|
|
break;
|
1994-06-20 04:35:39 +04:00
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
case NPMODE_QUEUE:
|
|
|
|
mpp = &m->m_nextpkt;
|
|
|
|
break;
|
|
|
|
}
|
1995-07-04 10:28:17 +04:00
|
|
|
}
|
2014-07-01 19:03:58 +04:00
|
|
|
sc->sc_npqtail = mpp;
|
1995-07-04 10:28:17 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1997-03-12 23:26:46 +03:00
|
|
|
* Transmitter has finished outputting some stuff;
|
|
|
|
* remember to call sc->sc_start later at splsoftnet.
|
1995-07-04 10:28:17 +04:00
|
|
|
*/
|
1997-03-12 23:26:46 +03:00
|
|
|
void
|
2005-12-12 02:05:24 +03:00
|
|
|
ppp_restart(struct ppp_softc *sc)
|
1995-07-04 10:28:17 +04:00
|
|
|
{
|
2014-07-01 19:03:58 +04:00
|
|
|
int s = splhigh(); /* XXX IMP ME HARDER */
|
1995-07-04 10:28:17 +04:00
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
sc->sc_flags &= ~SC_TBUSY;
|
|
|
|
softint_schedule(sc->sc_si);
|
|
|
|
splx(s);
|
1995-07-04 10:28:17 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1997-03-12 23:26:46 +03:00
|
|
|
* Get a packet to send. This procedure is intended to be called at
|
|
|
|
* splsoftnet, since it may involve time-consuming operations such as
|
|
|
|
* applying VJ compression, packet compression, address/control and/or
|
|
|
|
* protocol field compression to the packet.
|
1995-07-04 10:28:17 +04:00
|
|
|
*/
|
1997-03-12 23:26:46 +03:00
|
|
|
struct mbuf *
|
2005-12-12 02:05:24 +03:00
|
|
|
ppp_dequeue(struct ppp_softc *sc)
|
1995-07-04 10:28:17 +04:00
|
|
|
{
|
2014-07-01 19:03:58 +04:00
|
|
|
struct mbuf *m, *mp;
|
|
|
|
u_char *cp;
|
|
|
|
int address, control, protocol;
|
|
|
|
int s;
|
2005-02-27 01:45:09 +03:00
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
/*
|
|
|
|
* Grab a packet to send: first try the fast queue, then the
|
|
|
|
* normal queue.
|
|
|
|
*/
|
|
|
|
s = splnet();
|
|
|
|
if (sc->sc_nfastq < sc->sc_maxfastq) {
|
|
|
|
IF_DEQUEUE(&sc->sc_fastq, m);
|
|
|
|
if (m != NULL)
|
|
|
|
sc->sc_nfastq++;
|
|
|
|
else
|
|
|
|
IFQ_DEQUEUE(&sc->sc_if.if_snd, m);
|
|
|
|
} else {
|
|
|
|
sc->sc_nfastq = 0;
|
|
|
|
IFQ_DEQUEUE(&sc->sc_if.if_snd, m);
|
|
|
|
if (m == NULL) {
|
|
|
|
IF_DEQUEUE(&sc->sc_fastq, m);
|
|
|
|
if (m != NULL)
|
|
|
|
sc->sc_nfastq++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
splx(s);
|
1995-07-04 10:28:17 +04:00
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
if (m == NULL)
|
|
|
|
return NULL;
|
1996-03-15 05:28:00 +03:00
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
++sc->sc_stats.ppp_opackets;
|
1995-07-04 10:28:17 +04:00
|
|
|
|
|
|
|
/*
|
2014-07-01 19:03:58 +04:00
|
|
|
* Extract the ppp header of the new packet.
|
|
|
|
* The ppp header will be in one mbuf.
|
1995-07-04 10:28:17 +04:00
|
|
|
*/
|
2014-07-01 19:03:58 +04:00
|
|
|
cp = mtod(m, u_char *);
|
|
|
|
address = PPP_ADDRESS(cp);
|
|
|
|
control = PPP_CONTROL(cp);
|
|
|
|
protocol = PPP_PROTOCOL(cp);
|
|
|
|
|
|
|
|
switch (protocol) {
|
|
|
|
case PPP_IP:
|
|
|
|
#ifdef VJC
|
|
|
|
/*
|
|
|
|
* If the packet is a TCP/IP packet, see if we can compress it.
|
|
|
|
*/
|
|
|
|
if ((sc->sc_flags & SC_COMP_TCP) && sc->sc_comp != NULL) {
|
|
|
|
struct ip *ip;
|
|
|
|
int type;
|
|
|
|
|
|
|
|
mp = m;
|
2022-07-06 11:06:59 +03:00
|
|
|
ip = (struct ip *)(cp + PPP_HDRLEN);
|
2014-07-01 19:03:58 +04:00
|
|
|
if (mp->m_len <= PPP_HDRLEN) {
|
|
|
|
mp = mp->m_next;
|
|
|
|
if (mp == NULL)
|
|
|
|
break;
|
|
|
|
ip = mtod(mp, struct ip *);
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* This code assumes the IP/TCP header is in one
|
|
|
|
* non-shared mbuf
|
|
|
|
*/
|
|
|
|
if (ip->ip_p == IPPROTO_TCP) {
|
|
|
|
type = sl_compress_tcp(mp, ip, sc->sc_comp,
|
|
|
|
!(sc->sc_flags & SC_NO_TCP_CCID));
|
|
|
|
switch (type) {
|
|
|
|
case TYPE_UNCOMPRESSED_TCP:
|
|
|
|
protocol = PPP_VJC_UNCOMP;
|
|
|
|
break;
|
|
|
|
case TYPE_COMPRESSED_TCP:
|
|
|
|
protocol = PPP_VJC_COMP;
|
|
|
|
cp = mtod(m, u_char *);
|
|
|
|
cp[0] = address; /* Header has moved */
|
|
|
|
cp[1] = control;
|
|
|
|
cp[2] = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* Update protocol in PPP header */
|
|
|
|
cp[3] = protocol;
|
|
|
|
}
|
1994-06-20 04:35:39 +04:00
|
|
|
}
|
1994-05-08 16:33:49 +04:00
|
|
|
#endif /* VJC */
|
2014-07-01 19:03:58 +04:00
|
|
|
break;
|
1995-07-04 10:28:17 +04:00
|
|
|
|
|
|
|
#ifdef PPP_COMPRESS
|
2014-07-01 19:03:58 +04:00
|
|
|
case PPP_CCP:
|
|
|
|
ppp_ccp(sc, m, 0);
|
|
|
|
break;
|
1995-07-04 10:28:17 +04:00
|
|
|
#endif /* PPP_COMPRESS */
|
2014-07-01 19:03:58 +04:00
|
|
|
}
|
1994-05-08 16:33:49 +04:00
|
|
|
|
1995-07-04 10:28:17 +04:00
|
|
|
#ifdef PPP_COMPRESS
|
2022-07-06 11:06:59 +03:00
|
|
|
if (protocol != PPP_LCP && protocol != PPP_CCP &&
|
|
|
|
sc->sc_xc_state && (sc->sc_flags & SC_COMP_RUN)) {
|
2014-07-01 19:03:58 +04:00
|
|
|
struct mbuf *mcomp = NULL;
|
|
|
|
int slen;
|
|
|
|
|
|
|
|
slen = 0;
|
|
|
|
for (mp = m; mp != NULL; mp = mp->m_next)
|
|
|
|
slen += mp->m_len;
|
|
|
|
(*sc->sc_xcomp->compress)
|
|
|
|
(sc->sc_xc_state, &mcomp, m, slen, sc->sc_if.if_mtu + PPP_HDRLEN);
|
|
|
|
if (mcomp != NULL) {
|
|
|
|
if (sc->sc_flags & SC_CCP_UP) {
|
|
|
|
/*
|
|
|
|
* Send the compressed packet instead of the
|
|
|
|
* original.
|
|
|
|
*/
|
|
|
|
m_freem(m);
|
|
|
|
m = mcomp;
|
|
|
|
cp = mtod(m, u_char *);
|
|
|
|
protocol = cp[3];
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* Can't transmit compressed packets until CCP
|
|
|
|
* is up.
|
|
|
|
*/
|
|
|
|
m_freem(mcomp);
|
|
|
|
}
|
|
|
|
}
|
1995-07-04 10:28:17 +04:00
|
|
|
}
|
|
|
|
#endif /* PPP_COMPRESS */
|
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
/*
|
|
|
|
* Compress the address/control and protocol, if possible.
|
|
|
|
*/
|
|
|
|
if (sc->sc_flags & SC_COMP_AC && address == PPP_ALLSTATIONS &&
|
|
|
|
control == PPP_UI && protocol != PPP_ALLSTATIONS &&
|
|
|
|
protocol != PPP_LCP) {
|
|
|
|
/* can compress address/control */
|
|
|
|
m->m_data += 2;
|
|
|
|
m->m_len -= 2;
|
|
|
|
}
|
|
|
|
if (sc->sc_flags & SC_COMP_PROT && protocol < 0xFF) {
|
|
|
|
/* can compress protocol */
|
|
|
|
if (mtod(m, u_char *) == cp) {
|
|
|
|
cp[2] = cp[1]; /* move address/control up */
|
|
|
|
cp[1] = cp[0];
|
|
|
|
}
|
|
|
|
++m->m_data;
|
|
|
|
--m->m_len;
|
1994-05-08 16:33:49 +04:00
|
|
|
}
|
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
return m;
|
1997-03-12 23:26:46 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Software interrupt routine, called at splsoftnet.
|
|
|
|
*/
|
2005-12-12 02:05:24 +03:00
|
|
|
static void
|
2001-01-15 19:33:30 +03:00
|
|
|
pppintr(void *arg)
|
1997-03-12 23:26:46 +03:00
|
|
|
{
|
2001-01-15 19:33:30 +03:00
|
|
|
struct ppp_softc *sc = arg;
|
|
|
|
struct mbuf *m;
|
|
|
|
int s;
|
1997-03-12 23:26:46 +03:00
|
|
|
|
2008-04-24 15:38:36 +04:00
|
|
|
mutex_enter(softnet_lock);
|
2022-07-06 11:06:59 +03:00
|
|
|
if (!(sc->sc_flags & SC_TBUSY) &&
|
|
|
|
(IFQ_IS_EMPTY(&sc->sc_if.if_snd) == 0 ||
|
|
|
|
sc->sc_fastq.ifq_head ||
|
|
|
|
sc->sc_outm)) {
|
2001-04-14 03:29:55 +04:00
|
|
|
s = splhigh(); /* XXX IMP ME HARDER */
|
2001-01-15 19:33:30 +03:00
|
|
|
sc->sc_flags |= SC_TBUSY;
|
|
|
|
splx(s);
|
|
|
|
(*sc->sc_start)(sc);
|
1997-03-12 23:26:46 +03:00
|
|
|
}
|
|
|
|
for (;;) {
|
2001-04-14 03:29:55 +04:00
|
|
|
s = splnet();
|
2001-01-15 19:33:30 +03:00
|
|
|
IF_DEQUEUE(&sc->sc_rawq, m);
|
|
|
|
splx(s);
|
|
|
|
if (m == NULL)
|
|
|
|
break;
|
|
|
|
ppp_inproc(sc, m);
|
1997-03-12 23:26:46 +03:00
|
|
|
}
|
2008-04-24 15:38:36 +04:00
|
|
|
mutex_exit(softnet_lock);
|
1994-05-08 16:33:49 +04:00
|
|
|
}
|
|
|
|
|
1995-07-04 10:28:17 +04:00
|
|
|
#ifdef PPP_COMPRESS
|
1994-05-08 16:33:49 +04:00
|
|
|
/*
|
2014-07-01 19:03:58 +04:00
|
|
|
* Handle a CCP packet. `rcvd' is 1 if the packet was received,
|
1995-07-04 10:28:17 +04:00
|
|
|
* 0 if it is about to be transmitted.
|
1994-05-08 16:33:49 +04:00
|
|
|
*/
|
1996-02-14 00:59:53 +03:00
|
|
|
static void
|
2005-12-12 02:05:24 +03:00
|
|
|
ppp_ccp(struct ppp_softc *sc, struct mbuf *m, int rcvd)
|
1994-05-08 16:33:49 +04:00
|
|
|
{
|
2014-07-01 19:03:58 +04:00
|
|
|
u_char *dp, *ep;
|
|
|
|
struct mbuf *mp;
|
|
|
|
int slen, s;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get a pointer to the data after the PPP header.
|
|
|
|
*/
|
|
|
|
if (m->m_len <= PPP_HDRLEN) {
|
|
|
|
mp = m->m_next;
|
|
|
|
if (mp == NULL)
|
|
|
|
return;
|
|
|
|
dp = mtod(mp, u_char *);
|
|
|
|
} else {
|
|
|
|
mp = m;
|
|
|
|
dp = mtod(mp, u_char *) + PPP_HDRLEN;
|
1993-08-14 10:29:28 +04:00
|
|
|
}
|
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
ep = mtod(mp, u_char *) + mp->m_len;
|
|
|
|
if (dp + CCP_HDRLEN > ep)
|
|
|
|
return;
|
|
|
|
slen = CCP_LENGTH(dp);
|
|
|
|
if (dp + slen > ep) {
|
|
|
|
if (sc->sc_flags & SC_DEBUG)
|
|
|
|
printf("if_ppp/ccp: not enough data in mbuf (%p+%x > %p+%x)\n",
|
|
|
|
dp, slen, mtod(mp, u_char *), mp->m_len);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (CCP_CODE(dp)) {
|
|
|
|
case CCP_CONFREQ:
|
|
|
|
case CCP_TERMREQ:
|
|
|
|
case CCP_TERMACK:
|
|
|
|
/* CCP must be going down - disable compression */
|
|
|
|
if (sc->sc_flags & SC_CCP_UP) {
|
|
|
|
s = splhigh(); /* XXX IMP ME HARDER */
|
|
|
|
sc->sc_flags &= ~(SC_CCP_UP | SC_COMP_RUN | SC_DECOMP_RUN);
|
|
|
|
splx(s);
|
1993-08-14 10:29:28 +04:00
|
|
|
}
|
2014-07-01 19:03:58 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CCP_CONFACK:
|
2022-07-06 11:06:59 +03:00
|
|
|
if (sc->sc_flags & SC_CCP_OPEN &&
|
|
|
|
!(sc->sc_flags & SC_CCP_UP) &&
|
|
|
|
slen >= CCP_HDRLEN + CCP_OPT_MINLEN &&
|
|
|
|
slen >= CCP_OPT_LENGTH(dp + CCP_HDRLEN) + CCP_HDRLEN) {
|
2014-07-01 19:03:58 +04:00
|
|
|
if (!rcvd) {
|
|
|
|
/* We're agreeing to send compressed packets. */
|
2022-07-06 11:06:59 +03:00
|
|
|
if (sc->sc_xc_state != NULL &&
|
|
|
|
(*sc->sc_xcomp->comp_init)(sc->sc_xc_state,
|
|
|
|
dp + CCP_HDRLEN, slen - CCP_HDRLEN,
|
|
|
|
sc->sc_unit, 0,
|
2014-07-01 19:03:58 +04:00
|
|
|
sc->sc_flags & SC_DEBUG)) {
|
|
|
|
s = splhigh(); /* XXX IMP ME HARDER */
|
|
|
|
sc->sc_flags |= SC_COMP_RUN;
|
|
|
|
splx(s);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* Peer is agreeing to send compressed
|
|
|
|
* packets.
|
|
|
|
*/
|
2022-07-06 11:06:59 +03:00
|
|
|
if (sc->sc_rc_state != NULL &&
|
|
|
|
(*sc->sc_rcomp->decomp_init)(
|
|
|
|
sc->sc_rc_state,
|
|
|
|
dp + CCP_HDRLEN, slen - CCP_HDRLEN,
|
2014-07-01 19:03:58 +04:00
|
|
|
sc->sc_unit, 0, sc->sc_mru,
|
|
|
|
sc->sc_flags & SC_DEBUG)) {
|
|
|
|
s = splhigh(); /* XXX IMP ME HARDER */
|
|
|
|
sc->sc_flags |= SC_DECOMP_RUN;
|
2022-07-06 11:06:59 +03:00
|
|
|
sc->sc_flags &=
|
|
|
|
~(SC_DC_ERROR | SC_DC_FERROR);
|
2014-07-01 19:03:58 +04:00
|
|
|
splx(s);
|
|
|
|
}
|
|
|
|
}
|
1993-08-14 10:29:28 +04:00
|
|
|
}
|
2014-07-01 19:03:58 +04:00
|
|
|
break;
|
1993-08-31 04:05:27 +04:00
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
case CCP_RESETACK:
|
|
|
|
if (sc->sc_flags & SC_CCP_UP) {
|
|
|
|
if (!rcvd) {
|
|
|
|
if (sc->sc_xc_state && (sc->sc_flags & SC_COMP_RUN))
|
|
|
|
(*sc->sc_xcomp->comp_reset)(sc->sc_xc_state);
|
|
|
|
} else {
|
|
|
|
if (sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN)) {
|
|
|
|
(*sc->sc_rcomp->decomp_reset)(sc->sc_rc_state);
|
|
|
|
s = splhigh(); /* XXX IMP ME HARDER */
|
|
|
|
sc->sc_flags &= ~SC_DC_ERROR;
|
|
|
|
splx(s);
|
|
|
|
}
|
|
|
|
}
|
1995-07-04 10:28:17 +04:00
|
|
|
}
|
2014-07-01 19:03:58 +04:00
|
|
|
break;
|
1993-08-31 04:05:27 +04:00
|
|
|
}
|
1993-08-14 10:29:28 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1995-07-04 10:28:17 +04:00
|
|
|
* CCP is down; free (de)compressor state if necessary.
|
1993-08-14 10:29:28 +04:00
|
|
|
*/
|
1995-07-04 10:28:17 +04:00
|
|
|
static void
|
2005-12-12 02:05:24 +03:00
|
|
|
ppp_ccp_closed(struct ppp_softc *sc)
|
1993-08-14 10:29:28 +04:00
|
|
|
{
|
2014-07-01 19:03:58 +04:00
|
|
|
if (sc->sc_xc_state) {
|
|
|
|
(*sc->sc_xcomp->comp_free)(sc->sc_xc_state);
|
|
|
|
ppp_compressor_rele(sc->sc_xcomp);
|
|
|
|
sc->sc_xc_state = NULL;
|
|
|
|
}
|
|
|
|
if (sc->sc_rc_state) {
|
|
|
|
(*sc->sc_rcomp->decomp_free)(sc->sc_rc_state);
|
|
|
|
ppp_compressor_rele(sc->sc_rcomp);
|
|
|
|
sc->sc_rc_state = NULL;
|
|
|
|
}
|
1993-08-14 10:29:28 +04:00
|
|
|
}
|
1995-07-04 10:28:17 +04:00
|
|
|
#endif /* PPP_COMPRESS */
|
1993-08-14 10:29:28 +04:00
|
|
|
|
|
|
|
/*
|
1994-05-08 16:33:49 +04:00
|
|
|
* PPP packet input routine.
|
1994-06-20 04:35:39 +04:00
|
|
|
* The caller has checked and removed the FCS and has inserted
|
|
|
|
* the address/control bytes and the protocol high byte if they
|
1995-07-04 10:28:17 +04:00
|
|
|
* were omitted.
|
|
|
|
*/
|
|
|
|
void
|
2005-12-12 02:05:24 +03:00
|
|
|
ppppktin(struct ppp_softc *sc, struct mbuf *m, int lost)
|
1995-07-04 10:28:17 +04:00
|
|
|
{
|
2014-07-01 19:03:58 +04:00
|
|
|
int s = splhigh(); /* XXX IMP ME HARDER */
|
1995-07-04 10:28:17 +04:00
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
if (lost)
|
|
|
|
m->m_flags |= M_ERRMARK;
|
|
|
|
IF_ENQUEUE(&sc->sc_rawq, m);
|
|
|
|
softint_schedule(sc->sc_si);
|
|
|
|
splx(s);
|
1995-07-04 10:28:17 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Process a received PPP packet, doing decompression as necessary.
|
|
|
|
* Should be called at splsoftnet.
|
1993-08-14 10:29:28 +04:00
|
|
|
*/
|
2022-07-06 11:06:59 +03:00
|
|
|
#define COMPTYPE(proto) \
|
|
|
|
((proto) == PPP_VJC_COMP ? TYPE_COMPRESSED_TCP \
|
|
|
|
: TYPE_UNCOMPRESSED_TCP)
|
1993-08-14 10:29:28 +04:00
|
|
|
|
1995-07-04 10:28:17 +04:00
|
|
|
static void
|
2005-12-12 02:05:24 +03:00
|
|
|
ppp_inproc(struct ppp_softc *sc, struct mbuf *m)
|
1994-05-08 16:33:49 +04:00
|
|
|
{
|
2014-07-01 19:03:58 +04:00
|
|
|
struct ifnet *ifp = &sc->sc_if;
|
|
|
|
pktqueue_t *pktq = NULL;
|
|
|
|
struct ifqueue *inq = NULL;
|
|
|
|
int s, ilen, proto, rv;
|
|
|
|
u_char *cp, adrs, ctrl;
|
|
|
|
struct mbuf *mp, *dmp = NULL;
|
2000-10-02 07:54:10 +04:00
|
|
|
#ifdef VJC
|
2014-07-01 19:03:58 +04:00
|
|
|
int xlen;
|
|
|
|
u_char *iphdr;
|
|
|
|
u_int hlen;
|
2000-10-02 07:54:10 +04:00
|
|
|
#endif
|
1994-05-08 16:33:49 +04:00
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
sc->sc_stats.ppp_ipackets++;
|
1995-07-04 10:28:17 +04:00
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
if (sc->sc_flags & SC_LOG_INPKT) {
|
|
|
|
ilen = 0;
|
|
|
|
for (mp = m; mp != NULL; mp = mp->m_next)
|
|
|
|
ilen += mp->m_len;
|
|
|
|
printf("%s: got %d bytes\n", ifp->if_xname, ilen);
|
|
|
|
pppdumpm(m);
|
|
|
|
}
|
1995-07-04 10:28:17 +04:00
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
cp = mtod(m, u_char *);
|
|
|
|
adrs = PPP_ADDRESS(cp);
|
|
|
|
ctrl = PPP_CONTROL(cp);
|
|
|
|
proto = PPP_PROTOCOL(cp);
|
1995-07-04 10:28:17 +04:00
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
if (m->m_flags & M_ERRMARK) {
|
|
|
|
m->m_flags &= ~M_ERRMARK;
|
|
|
|
s = splhigh(); /* XXX IMP ME HARDER */
|
|
|
|
sc->sc_flags |= SC_VJ_RESET;
|
|
|
|
splx(s);
|
1995-07-04 10:28:17 +04:00
|
|
|
}
|
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
#ifdef PPP_COMPRESS
|
|
|
|
/*
|
|
|
|
* Decompress this packet if necessary, update the receiver's
|
|
|
|
* dictionary, or take appropriate action on a CCP packet.
|
|
|
|
*/
|
2022-07-06 11:06:59 +03:00
|
|
|
if (proto == PPP_COMP &&
|
|
|
|
sc->sc_rc_state &&
|
|
|
|
(sc->sc_flags & SC_DECOMP_RUN) &&
|
|
|
|
!(sc->sc_flags & SC_DC_ERROR) &&
|
|
|
|
!(sc->sc_flags & SC_DC_FERROR)) {
|
2014-07-01 19:03:58 +04:00
|
|
|
/* Decompress this packet */
|
|
|
|
rv = (*sc->sc_rcomp->decompress)(sc->sc_rc_state, m, &dmp);
|
|
|
|
if (rv == DECOMP_OK) {
|
|
|
|
m_freem(m);
|
|
|
|
if (dmp == NULL) {
|
|
|
|
/*
|
|
|
|
* No error, but no decompressed packet
|
|
|
|
* produced
|
|
|
|
*/
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
m = dmp;
|
|
|
|
cp = mtod(m, u_char *);
|
|
|
|
proto = PPP_PROTOCOL(cp);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* An error has occurred in decompression.
|
|
|
|
* Pass the compressed packet up to pppd, which may
|
|
|
|
* take CCP down or issue a Reset-Req.
|
|
|
|
*/
|
|
|
|
if (sc->sc_flags & SC_DEBUG)
|
|
|
|
printf("%s: decompress failed %d\n",
|
|
|
|
ifp->if_xname, rv);
|
|
|
|
s = splhigh(); /* XXX IMP ME HARDER */
|
|
|
|
sc->sc_flags |= SC_VJ_RESET;
|
|
|
|
if (rv == DECOMP_ERROR)
|
|
|
|
sc->sc_flags |= SC_DC_ERROR;
|
|
|
|
else
|
|
|
|
sc->sc_flags |= SC_DC_FERROR;
|
|
|
|
splx(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
if (sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN))
|
|
|
|
(*sc->sc_rcomp->incomp)(sc->sc_rc_state, m);
|
|
|
|
if (proto == PPP_CCP)
|
|
|
|
ppp_ccp(sc, m, 1);
|
1995-07-04 10:28:17 +04:00
|
|
|
}
|
|
|
|
#endif
|
1994-06-20 04:35:39 +04:00
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
ilen = 0;
|
|
|
|
for (mp = m; mp != NULL; mp = mp->m_next)
|
|
|
|
ilen += mp->m_len;
|
1996-02-07 15:43:41 +03:00
|
|
|
|
1994-05-08 16:33:49 +04:00
|
|
|
#ifdef VJC
|
2014-07-01 19:03:58 +04:00
|
|
|
if (sc->sc_flags & SC_VJ_RESET) {
|
|
|
|
/*
|
|
|
|
* If we've missed a packet, we must toss subsequent compressed
|
|
|
|
* packets which don't have an explicit connection ID.
|
|
|
|
*/
|
|
|
|
if (sc->sc_comp)
|
|
|
|
sl_uncompress_tcp(NULL, 0, TYPE_ERROR, sc->sc_comp);
|
|
|
|
s = splhigh(); /* XXX IMP ME HARDER */
|
|
|
|
sc->sc_flags &= ~SC_VJ_RESET;
|
|
|
|
splx(s);
|
1994-05-08 16:33:49 +04:00
|
|
|
}
|
|
|
|
|
1995-07-04 10:28:17 +04:00
|
|
|
/*
|
2014-07-01 19:03:58 +04:00
|
|
|
* See if we have a VJ-compressed packet to uncompress.
|
1995-07-04 10:28:17 +04:00
|
|
|
*/
|
2014-07-01 19:03:58 +04:00
|
|
|
if (proto == PPP_VJC_COMP) {
|
|
|
|
if ((sc->sc_flags & SC_REJ_COMP_TCP) || sc->sc_comp == 0)
|
|
|
|
goto bad;
|
|
|
|
|
|
|
|
xlen = sl_uncompress_tcp_core(cp + PPP_HDRLEN,
|
|
|
|
m->m_len - PPP_HDRLEN, ilen - PPP_HDRLEN,
|
|
|
|
TYPE_COMPRESSED_TCP, sc->sc_comp, &iphdr, &hlen);
|
|
|
|
if (xlen <= 0) {
|
2022-07-06 11:06:59 +03:00
|
|
|
if (sc->sc_flags & SC_DEBUG) {
|
|
|
|
printf("%s: VJ uncompress failed"
|
|
|
|
" on type comp\n",
|
2014-07-01 19:03:58 +04:00
|
|
|
ifp->if_xname);
|
2022-07-06 11:06:59 +03:00
|
|
|
}
|
2014-07-01 19:03:58 +04:00
|
|
|
goto bad;
|
|
|
|
}
|
1994-05-08 16:33:49 +04:00
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
/* Copy the PPP and IP headers into a new mbuf. */
|
|
|
|
MGETHDR(mp, M_DONTWAIT, MT_DATA);
|
|
|
|
if (mp == NULL)
|
|
|
|
goto bad;
|
|
|
|
mp->m_len = 0;
|
|
|
|
mp->m_next = NULL;
|
|
|
|
if (hlen + PPP_HDRLEN > MHLEN) {
|
|
|
|
MCLGET(mp, M_DONTWAIT);
|
|
|
|
if (M_TRAILINGSPACE(mp) < hlen + PPP_HDRLEN) {
|
|
|
|
/* Lose if big headers and no clusters */
|
|
|
|
m_freem(mp);
|
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
cp = mtod(mp, u_char *);
|
|
|
|
cp[0] = adrs;
|
|
|
|
cp[1] = ctrl;
|
|
|
|
cp[2] = 0;
|
|
|
|
cp[3] = PPP_IP;
|
|
|
|
proto = PPP_IP;
|
|
|
|
bcopy(iphdr, cp + PPP_HDRLEN, hlen);
|
|
|
|
mp->m_len = hlen + PPP_HDRLEN;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Trim the PPP and VJ headers off the old mbuf
|
|
|
|
* and stick the new and old mbufs together.
|
|
|
|
*/
|
|
|
|
m->m_data += PPP_HDRLEN + xlen;
|
|
|
|
m->m_len -= PPP_HDRLEN + xlen;
|
|
|
|
if (m->m_len <= M_TRAILINGSPACE(mp)) {
|
|
|
|
bcopy(mtod(m, u_char *),
|
|
|
|
mtod(mp, u_char *) + mp->m_len, m->m_len);
|
|
|
|
mp->m_len += m->m_len;
|
2016-10-02 17:16:02 +03:00
|
|
|
mp->m_next = m_free(m);
|
2014-07-01 19:03:58 +04:00
|
|
|
} else
|
|
|
|
mp->m_next = m;
|
|
|
|
m = mp;
|
|
|
|
ilen += hlen - xlen;
|
|
|
|
|
|
|
|
} else if (proto == PPP_VJC_UNCOMP) {
|
|
|
|
if ((sc->sc_flags & SC_REJ_COMP_TCP) || sc->sc_comp == 0)
|
|
|
|
goto bad;
|
|
|
|
|
|
|
|
xlen = sl_uncompress_tcp_core(cp + PPP_HDRLEN,
|
|
|
|
m->m_len - PPP_HDRLEN, ilen - PPP_HDRLEN,
|
|
|
|
TYPE_UNCOMPRESSED_TCP, sc->sc_comp, &iphdr, &hlen);
|
|
|
|
if (xlen < 0) {
|
2022-07-06 11:06:59 +03:00
|
|
|
if (sc->sc_flags & SC_DEBUG) {
|
|
|
|
printf("%s: VJ uncompress failed"
|
|
|
|
" on type uncomp\n",
|
2014-07-01 19:03:58 +04:00
|
|
|
ifp->if_xname);
|
2022-07-06 11:06:59 +03:00
|
|
|
}
|
2014-07-01 19:03:58 +04:00
|
|
|
goto bad;
|
|
|
|
}
|
1994-05-08 16:33:49 +04:00
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
proto = PPP_IP;
|
|
|
|
cp[3] = PPP_IP;
|
1994-06-20 04:35:39 +04:00
|
|
|
}
|
2014-07-01 19:03:58 +04:00
|
|
|
#endif /* VJC */
|
1994-05-08 16:33:49 +04:00
|
|
|
|
1997-03-12 23:26:46 +03:00
|
|
|
/*
|
2014-07-01 19:03:58 +04:00
|
|
|
* If the packet will fit in a header mbuf, don't waste a
|
|
|
|
* whole cluster on it.
|
1997-03-12 23:26:46 +03:00
|
|
|
*/
|
2019-09-20 11:45:29 +03:00
|
|
|
if (ilen <= MHLEN && (m->m_flags & M_EXT)) {
|
2014-07-01 19:03:58 +04:00
|
|
|
MGETHDR(mp, M_DONTWAIT, MT_DATA);
|
|
|
|
if (mp != NULL) {
|
|
|
|
m_copydata(m, 0, ilen, mtod(mp, void *));
|
|
|
|
m_freem(m);
|
|
|
|
m = mp;
|
|
|
|
m->m_len = ilen;
|
|
|
|
}
|
1996-03-15 05:28:00 +03:00
|
|
|
}
|
2014-07-01 19:03:58 +04:00
|
|
|
m->m_pkthdr.len = ilen;
|
2016-06-10 16:27:10 +03:00
|
|
|
m_set_rcvif(m, ifp);
|
2014-07-01 19:03:58 +04:00
|
|
|
|
|
|
|
if ((proto & 0x8000) == 0) {
|
|
|
|
#ifdef PPP_FILTER
|
|
|
|
/*
|
|
|
|
* See whether we want to pass this packet, and
|
|
|
|
* if it counts as link activity.
|
|
|
|
*/
|
2022-07-06 11:06:59 +03:00
|
|
|
if (sc->sc_pass_filt_in.bf_insns != 0 &&
|
|
|
|
bpf_filter(sc->sc_pass_filt_in.bf_insns,
|
2014-07-01 19:03:58 +04:00
|
|
|
(u_char *)m, ilen, 0) == 0) {
|
|
|
|
/* drop this packet */
|
|
|
|
m_freem(m);
|
|
|
|
return;
|
|
|
|
}
|
2022-07-06 11:06:59 +03:00
|
|
|
if (sc->sc_active_filt_in.bf_insns == 0 ||
|
|
|
|
bpf_filter(sc->sc_active_filt_in.bf_insns,
|
2014-07-01 19:03:58 +04:00
|
|
|
(u_char *)m, ilen, 0))
|
|
|
|
sc->sc_last_recv = time_second;
|
1997-03-12 23:26:46 +03:00
|
|
|
#else
|
2014-07-01 19:03:58 +04:00
|
|
|
/*
|
|
|
|
* Record the time that we received this packet.
|
|
|
|
*/
|
|
|
|
sc->sc_last_recv = time_second;
|
1997-03-12 23:26:46 +03:00
|
|
|
#endif /* PPP_FILTER */
|
2014-07-01 19:03:58 +04:00
|
|
|
}
|
1996-03-15 05:28:00 +03:00
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
/* See if bpf wants to look at the packet. */
|
2018-06-26 09:47:57 +03:00
|
|
|
bpf_mtap(&sc->sc_if, m, BPF_D_IN);
|
1994-05-08 16:33:49 +04:00
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
switch (proto) {
|
1994-05-08 16:33:49 +04:00
|
|
|
#ifdef INET
|
2014-07-01 19:03:58 +04:00
|
|
|
case PPP_IP:
|
|
|
|
/*
|
|
|
|
* IP packet - take off the ppp header and pass it up to IP.
|
|
|
|
*/
|
2022-07-06 11:06:59 +03:00
|
|
|
if ((ifp->if_flags & IFF_UP) == 0 ||
|
|
|
|
sc->sc_npmode[NP_IP] != NPMODE_PASS) {
|
2014-07-01 19:03:58 +04:00
|
|
|
/* Interface is down - drop the packet. */
|
|
|
|
m_freem(m);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
m->m_pkthdr.len -= PPP_HDRLEN;
|
|
|
|
m->m_data += PPP_HDRLEN;
|
|
|
|
m->m_len -= PPP_HDRLEN;
|
1998-07-10 02:30:01 +04:00
|
|
|
#ifdef GATEWAY
|
2014-07-01 19:03:58 +04:00
|
|
|
if (ipflow_fastforward(m))
|
|
|
|
return;
|
1998-07-10 02:30:01 +04:00
|
|
|
#endif
|
2014-07-01 19:03:58 +04:00
|
|
|
pktq = ip_pktq;
|
|
|
|
break;
|
1994-05-08 16:33:49 +04:00
|
|
|
#endif
|
|
|
|
|
1999-07-30 14:35:34 +04:00
|
|
|
#ifdef INET6
|
2014-07-01 19:03:58 +04:00
|
|
|
case PPP_IPV6:
|
|
|
|
/*
|
|
|
|
* IPv6 packet - take off the ppp header and pass it up to
|
|
|
|
* IPv6.
|
|
|
|
*/
|
2022-07-06 11:06:59 +03:00
|
|
|
if ((ifp->if_flags & IFF_UP) == 0 ||
|
|
|
|
sc->sc_npmode[NP_IPV6] != NPMODE_PASS) {
|
2014-07-01 19:03:58 +04:00
|
|
|
/* interface is down - drop the packet. */
|
|
|
|
m_freem(m);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
m->m_pkthdr.len -= PPP_HDRLEN;
|
|
|
|
m->m_data += PPP_HDRLEN;
|
|
|
|
m->m_len -= PPP_HDRLEN;
|
2022-07-06 11:06:59 +03:00
|
|
|
#ifdef GATEWAY
|
2014-07-01 19:03:58 +04:00
|
|
|
if (ip6flow_fastforward(&m))
|
|
|
|
return;
|
2007-03-08 01:20:04 +03:00
|
|
|
#endif
|
2014-07-01 19:03:58 +04:00
|
|
|
pktq = ip6_pktq;
|
|
|
|
break;
|
1999-07-30 14:35:34 +04:00
|
|
|
#endif
|
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
default:
|
|
|
|
/*
|
|
|
|
* Some other protocol - place on input queue for read().
|
|
|
|
*/
|
|
|
|
inq = &sc->sc_inq;
|
|
|
|
pktq = NULL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
1994-05-08 16:33:49 +04:00
|
|
|
/*
|
2014-07-01 19:03:58 +04:00
|
|
|
* Put the packet on the appropriate input queue.
|
1994-05-08 16:33:49 +04:00
|
|
|
*/
|
2014-07-01 19:03:58 +04:00
|
|
|
s = splnet();
|
|
|
|
|
|
|
|
/* pktq: inet or inet6 cases */
|
|
|
|
if (__predict_true(pktq)) {
|
|
|
|
if (__predict_false(!pktq_enqueue(pktq, m, 0))) {
|
2019-01-11 05:57:21 +03:00
|
|
|
splx(s);
|
2020-01-29 07:28:27 +03:00
|
|
|
if_statinc(ifp, if_iqdrops);
|
2014-07-01 19:03:58 +04:00
|
|
|
goto bad;
|
|
|
|
}
|
2020-01-29 07:28:27 +03:00
|
|
|
if_statadd2(ifp, if_ipackets, 1, if_ibytes, ilen);
|
2014-07-01 19:03:58 +04:00
|
|
|
splx(s);
|
|
|
|
return;
|
2014-06-06 03:48:16 +04:00
|
|
|
}
|
2014-07-01 19:03:58 +04:00
|
|
|
|
|
|
|
/* ifq: other protocol cases */
|
|
|
|
if (!inq) {
|
2019-01-11 05:57:21 +03:00
|
|
|
splx(s);
|
2014-07-01 19:03:58 +04:00
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
if (IF_QFULL(inq)) {
|
|
|
|
IF_DROP(inq);
|
|
|
|
splx(s);
|
|
|
|
if (sc->sc_flags & SC_DEBUG)
|
|
|
|
printf("%s: input queue full\n", ifp->if_xname);
|
2020-01-29 07:28:27 +03:00
|
|
|
if_statinc(ifp, if_iqdrops);
|
2014-07-01 19:03:58 +04:00
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
IF_ENQUEUE(inq, m);
|
|
|
|
splx(s);
|
2020-01-29 07:28:27 +03:00
|
|
|
if_statadd2(ifp, if_ipackets, 1, if_ibytes, ilen);
|
2014-07-01 19:03:58 +04:00
|
|
|
|
|
|
|
(*sc->sc_ctlp)(sc);
|
|
|
|
|
2014-06-06 03:48:16 +04:00
|
|
|
return;
|
2014-07-01 19:03:58 +04:00
|
|
|
|
|
|
|
bad:
|
|
|
|
m_freem(m);
|
2020-01-29 07:28:27 +03:00
|
|
|
if_statinc(&sc->sc_if, if_ierrors);
|
2014-07-01 19:03:58 +04:00
|
|
|
sc->sc_stats.ppp_ierrors++;
|
1993-08-14 10:29:28 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
#define MAX_DUMP_BYTES 128
|
|
|
|
|
|
|
|
static void
|
2005-12-12 02:05:24 +03:00
|
|
|
pppdumpm(struct mbuf *m0)
|
1993-08-14 10:29:28 +04:00
|
|
|
{
|
2014-07-01 19:03:58 +04:00
|
|
|
char buf[3*MAX_DUMP_BYTES+4];
|
|
|
|
char *bp = buf;
|
|
|
|
struct mbuf *m;
|
|
|
|
|
|
|
|
for (m = m0; m; m = m->m_next) {
|
|
|
|
int l = m->m_len;
|
|
|
|
u_char *rptr = (u_char *)m->m_data;
|
1993-08-14 10:29:28 +04:00
|
|
|
|
2014-07-01 19:03:58 +04:00
|
|
|
while (l--) {
|
|
|
|
if (bp > buf + sizeof(buf) - 4)
|
|
|
|
goto done;
|
|
|
|
/* Convert byte to ascii hex */
|
|
|
|
*bp++ = hexdigits[*rptr >> 4];
|
|
|
|
*bp++ = hexdigits[*rptr++ & 0xf];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m->m_next) {
|
|
|
|
if (bp > buf + sizeof(buf) - 3)
|
|
|
|
goto done;
|
|
|
|
*bp++ = '|';
|
|
|
|
} else
|
|
|
|
*bp++ = ' ';
|
|
|
|
}
|
1993-08-14 10:29:28 +04:00
|
|
|
done:
|
2014-07-01 19:03:58 +04:00
|
|
|
if (m)
|
|
|
|
*bp++ = '>';
|
|
|
|
*bp = 0;
|
|
|
|
printf("%s\n", buf);
|
1993-08-14 10:29:28 +04:00
|
|
|
}
|
2002-03-05 07:12:57 +03:00
|
|
|
|
|
|
|
#ifdef ALTQ
|
|
|
|
/*
|
2014-07-01 19:03:58 +04:00
|
|
|
* A wrapper to transmit a packet from if_start since ALTQ uses
|
2002-03-05 07:12:57 +03:00
|
|
|
* if_start to send a packet.
|
|
|
|
*/
|
|
|
|
static void
|
2005-12-12 02:05:24 +03:00
|
|
|
ppp_ifstart(struct ifnet *ifp)
|
2002-03-05 07:12:57 +03:00
|
|
|
{
|
|
|
|
struct ppp_softc *sc;
|
|
|
|
|
|
|
|
sc = ifp->if_softc;
|
|
|
|
(*sc->sc_start)(sc);
|
|
|
|
}
|
|
|
|
#endif
|
2008-11-25 05:40:36 +03:00
|
|
|
|
|
|
|
static const struct ppp_known_compressor {
|
|
|
|
uint8_t code;
|
|
|
|
const char *module;
|
|
|
|
} ppp_known_compressors[] = {
|
|
|
|
{ CI_DEFLATE, "ppp_deflate" },
|
|
|
|
{ CI_DEFLATE_DRAFT, "ppp_deflate" },
|
|
|
|
{ CI_BSD_COMPRESS, "ppp_bsdcomp" },
|
|
|
|
{ CI_MPPE, "ppp_mppe" },
|
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
|
2008-11-30 02:15:20 +03:00
|
|
|
static int
|
|
|
|
ppp_compressor_init(void)
|
|
|
|
{
|
|
|
|
|
|
|
|
mutex_init(&ppp_compressors_mtx, MUTEX_DEFAULT, IPL_NONE);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-08-06 05:35:05 +03:00
|
|
|
static int
|
|
|
|
ppp_compressor_destroy(void)
|
|
|
|
{
|
|
|
|
|
|
|
|
mutex_destroy(&ppp_compressors_mtx);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-11-30 02:15:20 +03:00
|
|
|
static void
|
|
|
|
ppp_compressor_rele(struct compressor *cp)
|
|
|
|
{
|
|
|
|
|
|
|
|
mutex_enter(&ppp_compressors_mtx);
|
|
|
|
--cp->comp_refcnt;
|
|
|
|
mutex_exit(&ppp_compressors_mtx);
|
|
|
|
}
|
|
|
|
|
2008-11-25 05:40:36 +03:00
|
|
|
static struct compressor *
|
|
|
|
ppp_get_compressor_noload(uint8_t ci, bool hold)
|
|
|
|
{
|
|
|
|
struct compressor *cp;
|
|
|
|
|
2008-11-30 02:15:20 +03:00
|
|
|
KASSERT(mutex_owned(&ppp_compressors_mtx));
|
2008-11-25 05:40:36 +03:00
|
|
|
LIST_FOREACH(cp, &ppp_compressors, comp_list) {
|
|
|
|
if (cp->compress_proto == ci) {
|
2008-11-30 02:15:20 +03:00
|
|
|
if (hold)
|
|
|
|
++cp->comp_refcnt;
|
2008-11-25 05:40:36 +03:00
|
|
|
return cp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct compressor *
|
|
|
|
ppp_get_compressor(uint8_t ci)
|
|
|
|
{
|
2008-11-30 02:15:20 +03:00
|
|
|
struct compressor *cp = NULL;
|
2008-11-25 05:40:36 +03:00
|
|
|
const struct ppp_known_compressor *pkc;
|
|
|
|
|
2009-01-19 18:16:34 +03:00
|
|
|
mutex_enter(&ppp_compressors_mtx);
|
|
|
|
cp = ppp_get_compressor_noload(ci, true);
|
|
|
|
mutex_exit(&ppp_compressors_mtx);
|
|
|
|
if (cp != NULL)
|
|
|
|
return cp;
|
|
|
|
|
2010-08-21 17:19:39 +04:00
|
|
|
kernconfig_lock();
|
2008-11-30 02:15:20 +03:00
|
|
|
mutex_enter(&ppp_compressors_mtx);
|
|
|
|
cp = ppp_get_compressor_noload(ci, true);
|
|
|
|
mutex_exit(&ppp_compressors_mtx);
|
|
|
|
if (cp == NULL) {
|
|
|
|
/* Not found, so try to autoload a module */
|
|
|
|
for (pkc = ppp_known_compressors; pkc->module != NULL; pkc++) {
|
|
|
|
if (pkc->code == ci) {
|
|
|
|
if (module_autoload(pkc->module,
|
2014-07-01 19:03:58 +04:00
|
|
|
MODULE_CLASS_MISC) != 0)
|
2008-11-30 02:15:20 +03:00
|
|
|
break;
|
|
|
|
mutex_enter(&ppp_compressors_mtx);
|
|
|
|
cp = ppp_get_compressor_noload(ci, true);
|
|
|
|
mutex_exit(&ppp_compressors_mtx);
|
2008-11-25 05:40:36 +03:00
|
|
|
break;
|
2008-11-30 02:15:20 +03:00
|
|
|
}
|
2008-11-25 05:40:36 +03:00
|
|
|
}
|
|
|
|
}
|
2010-08-21 17:19:39 +04:00
|
|
|
kernconfig_unlock();
|
2008-11-25 05:40:36 +03:00
|
|
|
|
2008-11-30 02:15:20 +03:00
|
|
|
return cp;
|
2008-11-25 05:40:36 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2008-11-30 02:15:20 +03:00
|
|
|
ppp_register_compressor(struct compressor *pc, size_t ncomp)
|
2008-11-25 05:40:36 +03:00
|
|
|
{
|
2008-11-30 02:15:20 +03:00
|
|
|
int error = 0;
|
|
|
|
size_t i;
|
2008-11-25 05:40:36 +03:00
|
|
|
|
|
|
|
mutex_enter(&ppp_compressors_mtx);
|
2008-11-30 02:15:20 +03:00
|
|
|
for (i = 0; i < ncomp; i++) {
|
|
|
|
if (ppp_get_compressor_noload(pc[i].compress_proto,
|
2014-07-01 19:03:58 +04:00
|
|
|
false) != NULL)
|
2008-11-30 02:15:20 +03:00
|
|
|
error = EEXIST;
|
|
|
|
}
|
|
|
|
if (!error) {
|
|
|
|
for (i = 0; i < ncomp; i++) {
|
|
|
|
pc[i].comp_refcnt = 0;
|
|
|
|
LIST_INSERT_HEAD(&ppp_compressors, &pc[i], comp_list);
|
|
|
|
}
|
|
|
|
}
|
2008-11-25 05:40:36 +03:00
|
|
|
mutex_exit(&ppp_compressors_mtx);
|
|
|
|
|
2008-11-30 02:15:20 +03:00
|
|
|
return error;
|
2008-11-25 05:40:36 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2008-11-30 02:15:20 +03:00
|
|
|
ppp_unregister_compressor(struct compressor *pc, size_t ncomp)
|
2008-11-25 05:40:36 +03:00
|
|
|
{
|
2008-11-30 02:15:20 +03:00
|
|
|
int error = 0;
|
|
|
|
size_t i;
|
2008-11-25 05:40:36 +03:00
|
|
|
|
|
|
|
mutex_enter(&ppp_compressors_mtx);
|
2008-11-30 02:15:20 +03:00
|
|
|
for (i = 0; i < ncomp; i++) {
|
|
|
|
if (ppp_get_compressor_noload(pc[i].compress_proto,
|
2014-07-01 19:03:58 +04:00
|
|
|
false) != &pc[i])
|
2008-11-30 02:15:20 +03:00
|
|
|
error = ENOENT;
|
|
|
|
else if (pc[i].comp_refcnt != 0)
|
|
|
|
error = EBUSY;
|
|
|
|
}
|
|
|
|
if (!error) {
|
|
|
|
for (i = 0; i < ncomp; i++) {
|
|
|
|
LIST_REMOVE(&pc[i], comp_list);
|
|
|
|
}
|
|
|
|
}
|
2008-11-25 05:40:36 +03:00
|
|
|
mutex_exit(&ppp_compressors_mtx);
|
|
|
|
|
2008-11-30 02:15:20 +03:00
|
|
|
return error;
|
2008-11-25 05:40:36 +03:00
|
|
|
}
|
2016-08-06 05:35:05 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Module infrastructure
|
|
|
|
*/
|
2016-08-07 20:38:33 +03:00
|
|
|
#include "if_module.h"
|
2016-08-06 05:35:05 +03:00
|
|
|
|
|
|
|
#ifdef PPP_FILTER
|
|
|
|
#define PPP_DEP "bpf_filter,"
|
|
|
|
#else
|
|
|
|
#define PPP_DEP
|
|
|
|
#endif
|
|
|
|
|
2016-08-07 20:38:33 +03:00
|
|
|
IF_MODULE(MODULE_CLASS_DRIVER, ppp, PPP_DEP "slcompress")
|