patch-2.4.22 linux-2.4.22/drivers/isdn/isdn_ppp.c
Next file: linux-2.4.22/drivers/isdn/isdn_ppp.h
Previous file: linux-2.4.22/drivers/isdn/isdn_net.c
Back to the patch index
Back to the overall index
- Lines: 411
- Date:
2003-08-25 04:44:42.000000000 -0700
- Orig file:
linux-2.4.21/drivers/isdn/isdn_ppp.c
- Orig date:
2003-06-13 07:51:34.000000000 -0700
diff -urN linux-2.4.21/drivers/isdn/isdn_ppp.c linux-2.4.22/drivers/isdn/isdn_ppp.c
@@ -13,6 +13,9 @@
#include <linux/isdn.h>
#include <linux/poll.h>
#include <linux/ppp-comp.h>
+#ifdef CONFIG_IPPP_FILTER
+#include <linux/filter.h>
+#endif
#include "isdn_common.h"
#include "isdn_ppp.h"
@@ -108,8 +111,8 @@
struct ippp_struct *is;
if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) {
- printk(KERN_ERR __FUNCTION__": ppp_slot(%d) out of range\n",
- lp->ppp_slot);
+ printk(KERN_ERR "%s: ppp_slot(%d) out of range\n",
+ __FUNCTION__, lp->ppp_slot);
return 0;
}
@@ -128,8 +131,8 @@
spin_unlock(&lp->netdev->pb->lock);
#endif /* CONFIG_ISDN_MPP */
if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) {
- printk(KERN_ERR __FUNCTION__": ppp_slot(%d) now invalid\n",
- lp->ppp_slot);
+ printk(KERN_ERR "%s: ppp_slot(%d) now invalid\n",
+ __FUNCTION__, lp->ppp_slot);
restore_flags(flags);
return 0;
}
@@ -229,8 +232,8 @@
isdn_ppp_wakeup_daemon(isdn_net_local * lp)
{
if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) {
- printk(KERN_ERR __FUNCTION__": ppp_slot(%d) out of range\n",
- lp->ppp_slot);
+ printk(KERN_ERR "%s: ppp_slot(%d) out of range\n",
+ __FUNCTION__, lp->ppp_slot);
return;
}
ippp_table[lp->ppp_slot]->state = IPPP_OPEN | IPPP_CONNECT | IPPP_NOBLOCK;
@@ -248,8 +251,8 @@
struct ippp_struct *is;
if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
- printk(KERN_ERR __FUNCTION__": slot(%d) out of range\n",
- slot);
+ printk(KERN_ERR "%s: slot(%d) out of range\n",
+ __FUNCTION__, slot);
return 0;
}
is = ippp_table[slot];
@@ -324,7 +327,10 @@
*/
is->slcomp = slhc_init(16, 16); /* not necessary for 2. link in bundle */
#endif
-
+#ifdef CONFIG_IPPP_FILTER
+ is->pass_filter.filter = NULL;
+ is->active_filter.filter = NULL;
+#endif
is->state = IPPP_OPEN;
return 0;
@@ -344,7 +350,7 @@
is = file->private_data;
if (!is) {
- printk(KERN_ERR __FUNCTION__": no file->private_data\n");
+ printk(KERN_ERR "%s: no file->private_data\n", __FUNCTION__);
return;
}
if (is->debug & 0x1)
@@ -354,7 +360,7 @@
isdn_net_dev *p = is->lp->netdev;
if (!p) {
- printk(KERN_ERR __FUNCTION__": no lp->netdev\n");
+ printk(KERN_ERR "%s: no lp->netdev\n", __FUNCTION__);
return;
}
is->state &= ~IPPP_CONNECT; /* -> effect: no call of wakeup */
@@ -379,6 +385,16 @@
slhc_free(is->slcomp);
is->slcomp = NULL;
#endif
+#ifdef CONFIG_IPPP_FILTER
+ if (is->pass_filter.filter) {
+ kfree(is->pass_filter.filter);
+ is->pass_filter.filter = NULL;
+ }
+ if (is->active_filter.filter) {
+ kfree(is->active_filter.filter);
+ is->active_filter.filter = NULL;
+ }
+#endif
/* TODO: if this was the previous master: link the stuff to the new master */
if(is->comp_stat)
@@ -588,6 +604,39 @@
}
return set_arg((void *)arg,&pci,sizeof(struct pppcallinfo));
}
+#ifdef CONFIG_IPPP_FILTER
+ case PPPIOCSPASS:
+ case PPPIOCSACTIVE:
+ {
+ struct sock_fprog uprog, *filtp;
+ struct sock_filter *code = NULL;
+ int len, err;
+
+ if (copy_from_user(&uprog, (void *) arg, sizeof(uprog)))
+ return -EFAULT;
+ if (uprog.len > 0 && uprog.len < 65536) {
+ len = uprog.len * sizeof(struct sock_filter);
+ code = kmalloc(len, GFP_KERNEL);
+ if (code == NULL)
+ return -ENOMEM;
+ if (copy_from_user(code, uprog.filter, len)) {
+ kfree(code);
+ return -EFAULT;
+ }
+ err = sk_chk_filter(code, uprog.len);
+ if (err) {
+ kfree(code);
+ return err;
+ }
+ }
+ filtp = (cmd == PPPIOCSPASS) ? &is->pass_filter : &is->active_filter;
+ if (filtp->filter)
+ kfree(filtp->filter);
+ filtp->filter = code;
+ filtp->len = uprog.len;
+ break;
+ }
+#endif /* CONFIG_IPPP_FILTER */
default:
break;
}
@@ -977,6 +1026,7 @@
{
struct net_device *dev = &net_dev->dev;
struct ippp_struct *is, *mis;
+ isdn_net_local *mlp = NULL;
int slot;
slot = lp->ppp_slot;
@@ -988,7 +1038,8 @@
is = ippp_table[slot];
if (lp->master) { // FIXME?
- slot = ((isdn_net_local *) (lp->master->priv))->ppp_slot;
+ mlp = (isdn_net_local *) lp->master->priv;
+ slot = mlp->ppp_slot;
if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
printk(KERN_ERR "isdn_ppp_push_higher: master->ppp_slot(%d)\n",
lp->ppp_slot);
@@ -1026,8 +1077,8 @@
if (is->debug & 0x20)
printk(KERN_DEBUG "isdn_ppp: VJC_UNCOMP\n");
if (net_dev->local->ppp_slot < 0) {
- printk(KERN_ERR __FUNCTION__": net_dev->local->ppp_slot(%d) out of range\n",
- net_dev->local->ppp_slot);
+ printk(KERN_ERR "%s: net_dev->local->ppp_slot(%d) out of range\n",
+ __FUNCTION__, net_dev->local->ppp_slot);
goto drop_packet;
}
if (slhc_remember(ippp_table[net_dev->local->ppp_slot]->slcomp, skb->data, skb->len) <= 0) {
@@ -1052,8 +1103,8 @@
skb_put(skb, skb_old->len + 128);
memcpy(skb->data, skb_old->data, skb_old->len);
if (net_dev->local->ppp_slot < 0) {
- printk(KERN_ERR __FUNCTION__": net_dev->local->ppp_slot(%d) out of range\n",
- net_dev->local->ppp_slot);
+ printk(KERN_ERR "%s: net_dev->local->ppp_slot(%d) out of range\n",
+ __FUNCTION__, net_dev->local->ppp_slot);
goto drop_packet;
}
pkt_len = slhc_uncompress(ippp_table[net_dev->local->ppp_slot]->slcomp,
@@ -1082,9 +1133,36 @@
return;
}
- /* Reset hangup-timer */
- lp->huptimer = 0;
-
+#ifdef CONFIG_IPPP_FILTER
+ /* check if the packet passes the pass and active filters
+ * the filter instructions are constructed assuming
+ * a four-byte PPP header on each packet (which is still present) */
+ skb_push(skb, 4);
+ skb->data[0] = 0; /* indicate inbound */
+
+ if (is->pass_filter.filter
+ && sk_run_filter(skb, is->pass_filter.filter,
+ is->pass_filter.len) == 0) {
+ if (is->debug & 0x2)
+ printk(KERN_DEBUG "IPPP: inbound frame filtered.\n");
+ kfree_skb(skb);
+ return;
+ }
+ if (!(is->active_filter.filter
+ && sk_run_filter(skb, is->active_filter.filter,
+ is->active_filter.len) == 0)) {
+ if (is->debug & 0x2)
+ printk(KERN_DEBUG "IPPP: link-active filter: reseting huptimer.\n");
+ lp->huptimer = 0;
+ if (mlp)
+ mlp->huptimer = 0;
+ }
+ skb_pull(skb, 4);
+#else /* CONFIG_IPPP_FILTER */
+ lp->huptimer = 0;
+ if (mlp)
+ mlp->huptimer = 0;
+#endif /* CONFIG_IPPP_FILTER */
skb->dev = dev;
skb->mac.raw = skb->data;
netif_rx(skb);
@@ -1121,7 +1199,6 @@
return skb_push(skb,len);
}
-
/*
* send ppp frame .. we expect a PIDCOMPressable proto --
* (here: currently always PPP_IP,PPP_VJC_COMP,PPP_VJC_UNCOMP)
@@ -1188,7 +1265,6 @@
goto unlock;
}
ipt = ippp_table[slot];
- lp->huptimer = 0;
/*
* after this line .. requeueing in the device queue is no longer allowed!!!
@@ -1199,6 +1275,34 @@
*/
skb_pull(skb,IPPP_MAX_HEADER);
+#ifdef CONFIG_IPPP_FILTER
+ /* check if we should pass this packet
+ * the filter instructions are constructed assuming
+ * a four-byte PPP header on each packet */
+ skb_push(skb, 4);
+ skb->data[0] = 1; /* indicate outbound */
+ *(u_int16_t *)(skb->data + 2) = htons(proto);
+
+ if (ipt->pass_filter.filter
+ && sk_run_filter(skb, ipt->pass_filter.filter,
+ ipt->pass_filter.len) == 0) {
+ if (ipt->debug & 0x4)
+ printk(KERN_DEBUG "IPPP: outbound frame filtered.\n");
+ kfree_skb(skb);
+ goto unlock;
+ }
+ if (!(ipt->active_filter.filter
+ && sk_run_filter(skb, ipt->active_filter.filter,
+ ipt->active_filter.len) == 0)) {
+ if (ipt->debug & 0x4)
+ printk(KERN_DEBUG "IPPP: link-active filter: reseting huptimer.\n");
+ lp->huptimer = 0;
+ }
+ skb_pull(skb, 4);
+#else /* CONFIG_IPPP_FILTER */
+ lp->huptimer = 0;
+#endif /* CONFIG_IPPP_FILTER */
+
if (ipt->debug & 0x4)
printk(KERN_DEBUG "xmit skb, len %d\n", (int) skb->len);
if (ipts->debug & 0x40)
@@ -1340,6 +1444,50 @@
return retval;
}
+#ifdef CONFIG_IPPP_FILTER
+/*
+ * check if this packet may trigger auto-dial.
+ */
+
+int isdn_ppp_autodial_filter(struct sk_buff *skb, isdn_net_local *lp)
+{
+ struct ippp_struct *is = ippp_table[lp->ppp_slot];
+ u_int16_t proto;
+ int drop = 0;
+
+ switch (ntohs(skb->protocol)) {
+ case ETH_P_IP:
+ proto = PPP_IP;
+ break;
+ case ETH_P_IPX:
+ proto = PPP_IPX;
+ break;
+ default:
+ printk(KERN_ERR "isdn_ppp_autodial_filter: unsupported protocol 0x%x.\n",
+ skb->protocol);
+ return 1;
+ }
+
+ /* the filter instructions are constructed assuming
+ * a four-byte PPP header on each packet. we have to
+ * temporarily remove part of the fake header stuck on
+ * earlier.
+ */
+ skb_pull(skb, IPPP_MAX_HEADER - 4);
+ skb->data[0] = 1; /* indicate outbound */
+ *(u_int16_t *)(skb->data + 2) = htons(proto);
+
+ drop |= is->pass_filter.filter
+ && sk_run_filter(skb, is->pass_filter.filter,
+ is->pass_filter.len) == 0;
+ drop |= is->active_filter.filter
+ && sk_run_filter(skb, is->active_filter.filter,
+ is->active_filter.len) == 0;
+
+ skb_push(skb, IPPP_MAX_HEADER - 4);
+ return drop;
+}
+#endif
#ifdef CONFIG_ISDN_MPP
/* this is _not_ rfc1990 header, but something we convert both short and long
@@ -1392,8 +1540,8 @@
struct ippp_struct * is;
if (lp->ppp_slot < 0) {
- printk(KERN_ERR __FUNCTION__": lp->ppp_slot(%d) out of range\n",
- lp->ppp_slot);
+ printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
+ __FUNCTION__, lp->ppp_slot);
return(-EINVAL);
}
@@ -1443,8 +1591,8 @@
stats = &mp->stats;
slot = lp->ppp_slot;
if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
- printk(KERN_ERR __FUNCTION__": lp->ppp_slot(%d)\n",
- lp->ppp_slot);
+ printk(KERN_ERR "%s: lp->ppp_slot(%d)\n",
+ __FUNCTION__, lp->ppp_slot);
stats->frame_drops++;
dev_kfree_skb(skb);
spin_unlock_irqrestore(&mp->lock, flags);
@@ -1480,8 +1628,8 @@
for (lpq = net_dev->queue;;) {
slot = lpq->ppp_slot;
if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
- printk(KERN_ERR __FUNCTION__": lpq->ppp_slot(%d)\n",
- lpq->ppp_slot);
+ printk(KERN_ERR "%s: lpq->ppp_slot(%d)\n",
+ __FUNCTION__, lpq->ppp_slot);
} else {
u32 lls = ippp_table[slot]->last_link_seqno;
if (MP_LT(lls, minseq))
@@ -1714,8 +1862,8 @@
unsigned int tot_len;
if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) {
- printk(KERN_ERR __FUNCTION__": lp->ppp_slot(%d) out of range\n",
- lp->ppp_slot);
+ printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
+ __FUNCTION__, lp->ppp_slot);
return;
}
if( MP_FLAGS(from) == (MP_BEGIN_FRAG | MP_END_FRAG) ) {
@@ -2491,8 +2639,8 @@
printk(KERN_DEBUG "Received CCP frame from peer slot(%d)\n",
lp->ppp_slot);
if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) {
- printk(KERN_ERR __FUNCTION__": lp->ppp_slot(%d) out of range\n",
- lp->ppp_slot);
+ printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
+ __FUNCTION__, lp->ppp_slot);
return;
}
is = ippp_table[lp->ppp_slot];
@@ -2501,8 +2649,8 @@
if(lp->master) {
int slot = ((isdn_net_local *) (lp->master->priv))->ppp_slot;
if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
- printk(KERN_ERR __FUNCTION__": slot(%d) out of range\n",
- slot);
+ printk(KERN_ERR "%s: slot(%d) out of range\n",
+ __FUNCTION__, slot);
return;
}
mis = ippp_table[slot];
@@ -2665,8 +2813,8 @@
if(!skb || skb->len < 3)
return;
if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
- printk(KERN_ERR __FUNCTION__": lp->ppp_slot(%d) out of range\n",
- slot);
+ printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
+ __FUNCTION__, slot);
return;
}
is = ippp_table[slot];
@@ -2688,8 +2836,8 @@
if (lp->master) {
slot = ((isdn_net_local *) (lp->master->priv))->ppp_slot;
if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
- printk(KERN_ERR __FUNCTION__": slot(%d) out of range\n",
- slot);
+ printk(KERN_ERR "%s: slot(%d) out of range\n",
+ __FUNCTION__, slot);
return;
}
mis = ippp_table[slot];
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)