* OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
* OR MODIFICATIONS.
*
- * $Id: ppp.c,v 1.6 1996/06/26 00:53:38 paulus Exp $
+ * $Id: ppp.c,v 1.14 1998/03/24 23:52:33 paulus Exp $
*/
/*
#include <net/pppio.h>
#include "ppp_mod.h"
+/*
+ * Modifications marked with #ifdef PRIOQ are for priority queueing of
+ * interactive traffic, and are due to Marko Zec <zec@japa.tel.fer.hr>.
+ */
+#ifdef PRIOQ
+#include <netinet/in.h>
+#endif /* PRIOQ */
+
#ifdef __STDC__
#define __P(x) x
#else
#define ETHERTYPE_IP 0x800
#endif
-#ifndef PPP_MAXMTU
-#define PPP_MAXMTU 65535
-#endif
-
extern time_t time;
/*
#define US_LASTMOD 8 /* no PPP modules below us */
#define US_DBGLOG 0x10 /* log various occurrences */
+
+#ifdef PRIOQ
+static u_char max_band=0;
+static u_char def_band=0;
+
+#define IPPORT_DEFAULT 65535
+
+/*
+ * Port priority table
+ * Highest priority ports are listed first, lowest are listed last.
+ * ICMP & packets using unlisted ports will be treated as "default".
+ * If IPPORT_DEFAULT is not listed here, "default" packets will be
+ * assigned lowest priority.
+ * Each line should be terminated with "0".
+ * Line containing only "0" marks the end of the list.
+ */
+
+static u_short prioq_table[]= {
+ 113, 53, 0,
+ 22, 23, 513, 517, 518, 0,
+ 514, 21, 79, 111, 0,
+ 25, 109, 110, 0,
+ IPPORT_DEFAULT, 0,
+ 20, 70, 80, 8001, 8008, 8080, 0, /* 8001,8008,8080 - common proxy ports */
+0 };
+
+#endif /* PRIOQ */
+
+
static upperstr_t *minor_devs = NULL;
static upperstr_t *ppas = NULL;
static int ppplwsrv __P((queue_t *));
#ifndef NO_DLPI
static void dlpi_request __P((queue_t *, mblk_t *, upperstr_t *));
-static void dlpi_error __P((queue_t *, int, int, int));
+static void dlpi_error __P((queue_t *, upperstr_t *, int, int, int));
static void dlpi_ok __P((queue_t *, int));
#endif
static int send_data __P((mblk_t *, upperstr_t *));
static upperstr_t *find_dest __P((upperstr_t *, int));
static int putctl2 __P((queue_t *, int, int, int));
static int putctl4 __P((queue_t *, int, int, int));
+static int pass_packet __P((upperstr_t *ppa, mblk_t *mp, int outbound));
+static int ip_hard_filter __P((upperstr_t *ppa, mblk_t *mp, int outbound));
#define PPP_ID 0xb1a6
static struct module_info ppp_info = {
+#ifdef PRIOQ
+ PPP_ID, "ppp", 0, 512, 512, 384
+#else
PPP_ID, "ppp", 0, 512, 512, 128
+#endif /* PRIOQ */
};
static struct qinit pppurint = {
upperstr_t *up;
upperstr_t **prevp;
minor_t mn;
+#ifdef PRIOQ
+ u_short *ptr;
+ u_char new_band;
+#endif /* PRIOQ */
if (q->q_ptr)
DRV_OPEN_OK(dev); /* device is already open */
+#ifdef PRIOQ
+ /* Calculate max_bband & def_band from definitions in prioq.h
+ This colud be done at some more approtiate time (less often)
+ but this way it works well so I'll just leave it here */
+
+ max_band = 1;
+ def_band = 0;
+ ptr = prioq_table;
+ while (*ptr) {
+ new_band = 1;
+ while (*ptr)
+ if (*ptr++ == IPPORT_DEFAULT) {
+ new_band = 0;
+ def_band = max_band;
+ }
+ max_band += new_band;
+ ptr++;
+ }
+ if (def_band)
+ def_band = max_band - def_band;
+ --max_band;
+#endif /* PRIOQ */
+
if (sflag == CLONEOPEN) {
mn = 0;
for (prevp = &minor_devs; (up = *prevp) != 0; prevp = &up->nextmn) {
qprocsoff(q);
up = (upperstr_t *) q->q_ptr;
+ if (up == 0) {
+ DPRINT("pppclose: q_ptr = 0\n");
+ return 0;
+ }
if (up->flags & US_DBGLOG)
DPRINT2("ppp/%d: close, flags=%x\n", up->mn, up->flags);
- if (up == 0)
- return 0;
if (up->flags & US_CONTROL) {
#ifdef LACHTCP
struct ifstats *ifp, *pifp;
mblk_t *mq;
struct ppp_idle *pip;
int len;
+#ifdef PRIOQ
+ queue_t *tlq;
+#endif /* PRIOQ */
us = (upperstr_t *) q->q_ptr;
+ if (us == 0) {
+ DPRINT("pppuwput: q_ptr = 0!\n");
+ return 0;
+ }
+ if (mp == 0) {
+ DPRINT1("pppuwput/%d: mp = 0!\n", us->mn);
+ return 0;
+ }
+ if (mp->b_datap == 0) {
+ DPRINT1("pppuwput/%d: mp->b_datap = 0!\n", us->mn);
+ return 0;
+ }
switch (mp->b_datap->db_type) {
#ifndef NO_DLPI
case M_PCPROTO:
break;
}
#ifdef NO_DLPI
- if (!pass_packet(us->ppa, mp, 1)) {
- freemsg(mp);
+ if ((us->flags & US_CONTROL) == 0 && !pass_packet(us, mp, 1))
break;
- }
#endif
if (!send_data(mp, us))
putq(q, mp);
case I_LINK:
if ((us->flags & US_CONTROL) == 0 || us->lowerq != 0)
break;
+ if (mp->b_cont == 0) {
+ DPRINT1("pppuwput/%d: ioctl I_LINK b_cont = 0!\n", us->mn);
+ break;
+ }
lb = (struct linkblk *) mp->b_cont->b_rptr;
us->lowerq = lq = lb->l_qbot;
+ if (lq == 0) {
+ DPRINT1("pppuwput/%d: ioctl I_LINK l_qbot = 0!\n", us->mn);
+ break;
+ }
lq->q_ptr = (caddr_t) us;
RD(lq)->q_ptr = (caddr_t) us;
noenable(RD(lq));
putctl2(lq, M_CTL, PPPCTL_UNIT, us->ppa_id);
putctl4(lq, M_CTL, PPPCTL_MRU, us->mru);
putctl4(lq, M_CTL, PPPCTL_MTU, us->mtu);
+#ifdef PRIOQ
+ /* Lower tty driver's queue hiwat/lowat from default 4096/128
+ to 256/128 since we don't want queueing of data on
+ output to physical device */
+
+ freezestr(lq);
+ for (tlq = lq; tlq->q_next != NULL; tlq = tlq->q_next)
+ ;
+ strqset(tlq, QHIWAT, 0, 256);
+ strqset(tlq, QLOWAT, 0, 128);
+ unfreezestr(lq);
+#endif /* PRIOQ */
break;
case I_UNLINK:
+ if (mp->b_cont == 0) {
+ DPRINT1("pppuwput/%d: ioctl I_UNLINK b_cont = 0!\n", us->mn);
+ break;
+ }
lb = (struct linkblk *) mp->b_cont->b_rptr;
#if DEBUG
- if (us->lowerq != lb->l_qbot)
+ if (us->lowerq != lb->l_qbot) {
DPRINT2("ppp unlink: lowerq=%x qbot=%x\n",
us->lowerq, lb->l_qbot);
+ break;
+ }
#endif
us->lowerq = 0;
iop->ioc_count = 0;
the stream (like pppstats) */
if (iop->ioc_count != sizeof(int) || us->ppa != 0)
break;
+ if (mp->b_cont == 0) {
+ DPRINT1("pppuwput/%d: ioctl PPPIO_ATTACH b_cont = 0!\n", us->mn);
+ break;
+ }
n = *(int *)mp->b_cont->b_rptr;
for (ppa = ppas; ppa != 0; ppa = ppa->nextppa)
if (ppa->ppa_id == n)
/* Attach to a given SAP. */
if (iop->ioc_count != sizeof(int) || us->ppa == 0)
break;
+ if (mp->b_cont == 0) {
+ DPRINT1("pppuwput/%d: ioctl PPPIO_BIND b_cont = 0!\n", us->mn);
+ break;
+ }
n = *(int *)mp->b_cont->b_rptr;
/* n must be a valid PPP network protocol number. */
if (n < 0x21 || n > 0x3fff || (n & 0x101) != 1)
case PPPIO_MRU:
if (iop->ioc_count != sizeof(int) || (us->flags & US_CONTROL) == 0)
break;
+ if (mp->b_cont == 0) {
+ DPRINT1("pppuwput/%d: ioctl PPPIO_MRU b_cont = 0!\n", us->mn);
+ break;
+ }
n = *(int *)mp->b_cont->b_rptr;
- if (n <= 0 || n > PPP_MAXMTU)
+ if (n <= 0 || n > PPP_MAXMRU)
break;
if (n < PPP_MRU)
n = PPP_MRU;
case PPPIO_MTU:
if (iop->ioc_count != sizeof(int) || (us->flags & US_CONTROL) == 0)
break;
+ if (mp->b_cont == 0) {
+ DPRINT1("pppuwput/%d: ioctl PPPIO_MTU b_cont = 0!\n", us->mn);
+ break;
+ }
n = *(int *)mp->b_cont->b_rptr;
if (n <= 0 || n > PPP_MAXMTU)
break;
- if (n < PPP_MRU)
- n = PPP_MRU;
us->mtu = n;
#ifdef LACHTCP
+ /* The MTU reported in netstat, not used as IP max packet size! */
us->ifstats.ifs_mtu = n;
#endif
if (us->lowerq)
case PPPIO_DEBUG:
if (iop->ioc_count != sizeof(int))
break;
+ if (mp->b_cont == 0) {
+ DPRINT1("pppuwput/%d: ioctl PPPIO_DEBUG b_cont = 0!\n", us->mn);
+ break;
+ }
n = *(int *)mp->b_cont->b_rptr;
if (n == PPPDBG_DUMP + PPPDBG_DRIVER) {
qwriter(q, NULL, debug_dump, PERIM_OUTER);
break;
if ((us->flags & US_CONTROL) == 0)
break;
+ if (mp->b_cont == 0) {
+ DPRINT1("pppuwput/%d: ioctl PPPIO_NPMODE b_cont = 0!\n", us->mn);
+ break;
+ }
sap = ((int *)mp->b_cont->b_rptr)[0];
for (nps = us->next; nps != 0; nps = nps->next)
if (nps->sap == sap)
#ifdef LACHTCP
case SIOCSIFNAME:
- printf("SIOCSIFNAME\n");
/* Sent from IP down to us. Attach the ifstats structure. */
if (iop->ioc_count != sizeof(struct ifreq) || us->ppa == 0)
break;
break;
case SIOCGIFFLAGS:
- printf("SIOCGIFFLAGS\n");
if (!(us->flags & US_CONTROL)) {
if (us->ppa)
us = us->ppa;
break;
case SIOCSIFFLAGS:
- printf("SIOCSIFFLAGS\n");
if (!(us->flags & US_CONTROL)) {
if (us->ppa)
us = us->ppa;
break;
case SIOCSIFADDR:
- printf("SIOCSIFADDR\n");
if (!(us->flags & US_CONTROL)) {
if (us->ppa)
us = us->ppa;
error = 0;
break;
+ case SIOCSIFMTU:
+ /*
+ * Vanilla SVR4 systems don't handle SIOCSIFMTU, rather
+ * they take the MTU from the DL_INFO_ACK we sent in response
+ * to their DL_INFO_REQ. Fortunately, they will update the
+ * MTU if we send an unsolicited DL_INFO_ACK up.
+ */
+ if ((mq = allocb(sizeof(dl_info_req_t), BPRI_HI)) == 0)
+ break; /* should do bufcall */
+ ((union DL_primitives *)mq->b_rptr)->dl_primitive = DL_INFO_REQ;
+ mq->b_wptr = mq->b_rptr + sizeof(dl_info_req_t);
+ dlpi_request(q, mq, us);
+ error = 0;
+ break;
+
case SIOCGIFNETMASK:
case SIOCSIFNETMASK:
case SIOCGIFADDR:
reply->b_wptr += sizeof(dl_info_ack_t);
bzero((caddr_t) info, sizeof(dl_info_ack_t));
info->dl_primitive = DL_INFO_ACK;
- info->dl_max_sdu = PPP_MAXMTU;
+ info->dl_max_sdu = us->ppa? us->ppa->mtu: PPP_MAXMTU;
info->dl_min_sdu = 1;
info->dl_addr_length = sizeof(ulong);
#ifdef DL_OTHER
if (size < sizeof(dl_attach_req_t))
goto badprim;
if (us->state != DL_UNATTACHED || us->ppa != 0) {
- dlpi_error(q, DL_ATTACH_REQ, DL_OUTSTATE, 0);
+ dlpi_error(q, us, DL_ATTACH_REQ, DL_OUTSTATE, 0);
break;
}
for (ppa = ppas; ppa != 0; ppa = ppa->nextppa)
if (ppa->ppa_id == d->attach_req.dl_ppa)
break;
if (ppa == 0) {
- dlpi_error(q, DL_ATTACH_REQ, DL_BADPPA, 0);
+ dlpi_error(q, us, DL_ATTACH_REQ, DL_BADPPA, 0);
break;
}
us->ppa = ppa;
if (size < sizeof(dl_detach_req_t))
goto badprim;
if (us->state != DL_UNBOUND || us->ppa == 0) {
- dlpi_error(q, DL_DETACH_REQ, DL_OUTSTATE, 0);
+ dlpi_error(q, us, DL_DETACH_REQ, DL_OUTSTATE, 0);
break;
}
qwriter(q, mp, detach_ppa, PERIM_OUTER);
if (size < sizeof(dl_bind_req_t))
goto badprim;
if (us->state != DL_UNBOUND || us->ppa == 0) {
- dlpi_error(q, DL_BIND_REQ, DL_OUTSTATE, 0);
+ dlpi_error(q, us, DL_BIND_REQ, DL_OUTSTATE, 0);
break;
}
+#if 0
+ /* apparently this test fails (unnecessarily?) on some systems */
if (d->bind_req.dl_service_mode != DL_CLDLS) {
- dlpi_error(q, DL_BIND_REQ, DL_UNSUPPORTED, 0);
+ dlpi_error(q, us, DL_BIND_REQ, DL_UNSUPPORTED, 0);
break;
}
+#endif
/* saps must be valid PPP network protocol numbers,
except that we accept ETHERTYPE_IP in place of PPP_IP. */
if (sap == ETHERTYPE_IP)
sap = PPP_IP;
if (sap < 0x21 || sap > 0x3fff || (sap & 0x101) != 1) {
- dlpi_error(q, DL_BIND_REQ, DL_BADADDR, 0);
+ dlpi_error(q, us, DL_BIND_REQ, DL_BADADDR, 0);
break;
}
if (os->sap == sap)
break;
if (os != 0) {
- dlpi_error(q, DL_BIND_REQ, DL_NOADDR, 0);
+ dlpi_error(q, us, DL_BIND_REQ, DL_NOADDR, 0);
break;
}
if (size < sizeof(dl_unbind_req_t))
goto badprim;
if (us->state != DL_IDLE) {
- dlpi_error(q, DL_UNBIND_REQ, DL_OUTSTATE, 0);
+ dlpi_error(q, us, DL_UNBIND_REQ, DL_OUTSTATE, 0);
break;
}
us->sap = -1;
if (size < sizeof(dl_unitdata_req_t))
goto badprim;
if (us->state != DL_IDLE) {
- dlpi_error(q, DL_UNITDATA_REQ, DL_OUTSTATE, 0);
+ dlpi_error(q, us, DL_UNITDATA_REQ, DL_OUTSTATE, 0);
break;
}
if ((ppa = us->ppa) == 0) {
DPRINT2("dlpi data too large (%d > %d)\n", len, ppa->mtu);
break;
}
+ mp->b_band = 0;
+#ifdef PRIOQ
+ /* Extract s_port & d_port from IP-packet, the code is a bit
+ dirty here, but so am I, too... */
+ if (mp->b_datap->db_type == M_PROTO && us->sap == PPP_IP
+ && mp->b_cont != 0) {
+ u_char *bb, *tlh;
+ int iphlen, len;
+ u_short *ptr;
+ u_char band_unset, cur_band, syn;
+ u_short s_port, d_port;
+
+ bb = mp->b_cont->b_rptr; /* bb points to IP-header*/
+ len = mp->b_cont->b_wptr - mp->b_cont->b_rptr;
+ syn = 0;
+ s_port = IPPORT_DEFAULT;
+ d_port = IPPORT_DEFAULT;
+ if (len >= 20) { /* 20 = minimum length of IP header */
+ iphlen = (bb[0] & 0x0f) * 4;
+ tlh = bb + iphlen;
+ len -= iphlen;
+ switch (bb[9]) {
+ case IPPROTO_TCP:
+ if (len >= 20) { /* min length of TCP header */
+ s_port = (tlh[0] << 8) + tlh[1];
+ d_port = (tlh[2] << 8) + tlh[3];
+ syn = tlh[13] & 0x02;
+ }
+ break;
+ case IPPROTO_UDP:
+ if (len >= 8) { /* min length of UDP header */
+ s_port = (tlh[0] << 8) + tlh[1];
+ d_port = (tlh[2] << 8) + tlh[3];
+ }
+ break;
+ }
+ }
+
+ /*
+ * Now calculate b_band for this packet from the
+ * port-priority table.
+ */
+ ptr = prioq_table;
+ cur_band = max_band;
+ band_unset = 1;
+ while (*ptr) {
+ while (*ptr && band_unset)
+ if (s_port == *ptr || d_port == *ptr++) {
+ mp->b_band = cur_band;
+ band_unset = 0;
+ break;
+ }
+ ptr++;
+ cur_band--;
+ }
+ if (band_unset)
+ mp->b_band = def_band;
+ /* It may be usable to urge SYN packets a bit */
+ if (syn)
+ mp->b_band++;
+ }
+#endif /* PRIOQ */
/* this assumes PPP_HDRLEN <= sizeof(dl_unitdata_req_t) */
if (mp->b_datap->db_ref > 1) {
np = allocb(PPP_HDRLEN, BPRI_HI);
mp->b_rptr[1] = PPP_UI;
mp->b_rptr[2] = us->sap >> 8;
mp->b_rptr[3] = us->sap;
- if (!pass_packet(ppa, mp, 1)) {
- freemsg(mp);
- } else {
+ if (pass_packet(us, mp, 1)) {
if (!send_data(mp, us))
putq(q, mp);
}
#endif
case DL_CONNECT_REQ:
case DL_TOKEN_REQ:
- dlpi_error(q, d->dl_primitive, DL_NOTSUPPORTED, 0);
+ dlpi_error(q, us, d->dl_primitive, DL_NOTSUPPORTED, 0);
break;
case DL_CONNECT_RES:
case DL_DISCONNECT_REQ:
case DL_RESET_REQ:
case DL_RESET_RES:
- dlpi_error(q, d->dl_primitive, DL_OUTSTATE, 0);
+ dlpi_error(q, us, d->dl_primitive, DL_OUTSTATE, 0);
break;
case DL_UDQOS_REQ:
- dlpi_error(q, d->dl_primitive, DL_BADQOSTYPE, 0);
+ dlpi_error(q, us, d->dl_primitive, DL_BADQOSTYPE, 0);
break;
#if DL_CURRENT_VERSION >= 2
cmn_err(CE_CONT, "ppp: unknown dlpi prim 0x%x\n", d->dl_primitive);
/* fall through */
badprim:
- dlpi_error(q, d->dl_primitive, DL_BADPRIM, 0);
+ dlpi_error(q, us, d->dl_primitive, DL_BADPRIM, 0);
break;
}
freemsg(mp);
}
static void
-dlpi_error(q, prim, err, uerr)
+dlpi_error(q, us, prim, err, uerr)
queue_t *q;
+ upperstr_t *us;
int prim, err, uerr;
{
mblk_t *reply;
dl_error_ack_t *errp;
+ if (us->flags & US_DBGLOG)
+ DPRINT3("ppp/%d: dlpi error, prim=%x, err=%x\n", us->mn, prim, err);
reply = allocb(sizeof(dl_error_ack_t), BPRI_HI);
if (reply == 0)
return; /* XXX should do bufcall */
#endif /* NO_DLPI */
static int
-pass_packet(ppa, mp, outbound)
- upperstr_t *ppa;
+pass_packet(us, mp, outbound)
+ upperstr_t *us;
mblk_t *mp;
int outbound;
{
+ int pass;
+ upperstr_t *ppa;
+
+ if ((ppa = us->ppa) == 0) {
+ freemsg(mp);
+ return 0;
+ }
+
+#ifdef FILTER_PACKETS
+ pass = ip_hard_filter(us, mp, outbound);
+#else
/*
* Here is where we might, in future, decide whether to pass
* or drop the packet, and whether it counts as link activity.
*/
- if (outbound)
- ppa->last_sent = time;
- else
- ppa->last_recv = time;
- return 1;
+ pass = 1;
+#endif /* FILTER_PACKETS */
+
+ if (pass < 0) {
+ /* pass only if link already up, and don't update time */
+ if (ppa->lowerq == 0) {
+ freemsg(mp);
+ return 0;
+ }
+ pass = 1;
+ } else if (pass) {
+ if (outbound)
+ ppa->last_sent = time;
+ else
+ ppa->last_recv = time;
+ }
+
+ return pass;
}
static int
}
if ((q = ppa->lowerq) == 0) {
/* try to send it up the control stream */
- if (canputnext(ppa->q)) {
- putnext(ppa->q, mp);
+ if (bcanputnext(ppa->q, mp->b_band)) {
+ /*
+ * The message seems to get corrupted for some reason if
+ * we just send the message up as it is, so we send a copy.
+ */
+ mblk_t *np = copymsg(mp);
+ freemsg(mp);
+ if (np != 0)
+ putnext(ppa->q, np);
return 1;
}
} else {
- if (canputnext(ppa->lowerq)) {
+ if (bcanputnext(ppa->lowerq, mp->b_band)) {
/*
* The lower write queue's put procedure just updates counters
* and does a putnext. We call it so that on SMP systems, we
us->flags |= US_CONTROL;
us->npmode = NPMODE_PASS;
- us->mtu = PPP_MRU;
+ us->mtu = PPP_MTU;
us->mru = PPP_MRU;
#ifdef SOL2
#ifdef INCR_IPACKETS
INCR_IPACKETS(ppa);
#endif
- if (!pass_packet(ppa, mp, 0)) {
- freemsg(mp);
- break;
- }
proto = PPP_PROTOCOL(mp->b_rptr);
if (proto < 0x8000 && (us = find_dest(ppa, proto)) != 0) {
/*
* A data packet for some network protocol.
* Queue it on the upper stream for that protocol.
*/
+ if (!pass_packet(us, mp, 0))
+ break;
if (canput(us->q))
putq(us->q, mp);
else
}
}
}
+
+#ifdef FILTER_PACKETS
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/udp.h>
+#include <netinet/tcp.h>
+
+#define MAX_IPHDR 128 /* max TCP/IP header size */
+
+
+/* The following table contains a hard-coded list of protocol/port pairs.
+ * Any matching packets are either discarded unconditionally, or,
+ * if ok_if_link_up is non-zero when a connection does not currently exist
+ * (i.e., they go through if the connection is present, but never initiate
+ * a dial-out).
+ * This idea came from a post by dm@garage.uun.org (David Mazieres)
+ */
+static struct pktfilt_tab {
+ int proto;
+ u_short port;
+ u_short ok_if_link_up;
+} pktfilt_tab[] = {
+ { IPPROTO_UDP, 520, 1 }, /* RIP, ok to pass if link is up */
+ { IPPROTO_UDP, 123, 1 }, /* NTP, don't keep up the link for it */
+ { -1, 0, 0 } /* terminator entry has port == -1 */
+};
+
+
+static int
+ip_hard_filter(us, mp, outbound)
+ upperstr_t *us;
+ mblk_t *mp;
+ int outbound;
+{
+ struct ip *ip;
+ struct pktfilt_tab *pft;
+ mblk_t *temp_mp;
+ int proto;
+ int len, hlen;
+
+
+ /* Note, the PPP header has already been pulled up in all cases */
+ proto = PPP_PROTOCOL(mp->b_rptr);
+ if (us->flags & US_DBGLOG)
+ DPRINT3("ppp/%d: filter, proto=0x%x, out=%d\n", us->mn, proto, outbound);
+
+ switch (proto)
+ {
+ case PPP_IP:
+ if ((mp->b_wptr - mp->b_rptr) == PPP_HDRLEN && mp->b_cont != 0) {
+ temp_mp = mp->b_cont;
+ len = msgdsize(temp_mp);
+ hlen = (len < MAX_IPHDR) ? len : MAX_IPHDR;
+ PULLUP(temp_mp, hlen);
+ if (temp_mp == 0) {
+ DPRINT2("ppp/%d: filter, pullup next failed, len=%d\n",
+ us->mn, hlen);
+ mp->b_cont = 0; /* PULLUP() freed the rest */
+ freemsg(mp);
+ return 0;
+ }
+ ip = (struct ip *)mp->b_cont->b_rptr;
+ }
+ else {
+ len = msgdsize(mp);
+ hlen = (len < (PPP_HDRLEN+MAX_IPHDR)) ? len : (PPP_HDRLEN+MAX_IPHDR);
+ PULLUP(mp, hlen);
+ if (mp == 0) {
+ DPRINT2("ppp/%d: filter, pullup failed, len=%d\n",
+ us->mn, hlen);
+ return 0;
+ }
+ ip = (struct ip *)(mp->b_rptr + PPP_HDRLEN);
+ }
+
+ /* For IP traffic, certain packets (e.g., RIP) may be either
+ * 1. ignored - dropped completely
+ * 2. will not initiate a connection, but
+ * will be passed if a connection is currently up.
+ */
+ for (pft=pktfilt_tab; pft->proto != -1; pft++) {
+ if (ip->ip_p == pft->proto) {
+ switch(pft->proto) {
+ case IPPROTO_UDP:
+ if (((struct udphdr *) &((int *)ip)[ip->ip_hl])->uh_dport
+ == htons(pft->port)) goto endfor;
+ break;
+ case IPPROTO_TCP:
+ if (((struct tcphdr *) &((int *)ip)[ip->ip_hl])->th_dport
+ == htons(pft->port)) goto endfor;
+ break;
+ }
+ }
+ }
+ endfor:
+ if (pft->proto != -1) {
+ if (us->flags & US_DBGLOG)
+ DPRINT3("ppp/%d: found IP pkt, proto=0x%x (%d)\n",
+ us->mn, pft->proto, pft->port);
+ /* Discard if not connected, or if not pass_with_link_up */
+ /* else, if link is up let go by, but don't update time */
+ return pft->ok_if_link_up? -1: 0;
+ }
+ break;
+ } /* end switch (proto) */
+
+ return 1;
+}
+#endif /* FILTER_PACKETS */
+