summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKai Germaschewski <kai@tp1.ruhr-uni-bochum.de>2002-10-16 01:17:39 -0500
committerKai Germaschewski <kai@tp1.ruhr-uni-bochum.de>2002-10-16 01:17:39 -0500
commit4edfad00c2a014728f006a16e2b2208e2ba75e95 (patch)
tree8e123cb252b145e050dd744b6ab26413962a901f
parentafd5fdbf2ed86b96b23fda3b2c47096764811788 (diff)
ISDN/PPP: PPP header cleanups
Use a shared function for generating the PPP header, use the {put,get}_u{8,16,32} helpers for endian-safe access.
-rw-r--r--drivers/isdn/i4l/isdn_ppp.c174
1 files changed, 69 insertions, 105 deletions
diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c
index 64caebad6055..8595e4e13e70 100644
--- a/drivers/isdn/i4l/isdn_ppp.c
+++ b/drivers/isdn/i4l/isdn_ppp.c
@@ -106,6 +106,30 @@ isdn_ppp_frame_log(char *info, char *data, int len, int maxlen,int unit,int slot
}
}
+
+void
+isdn_ppp_push_header(isdn_net_dev *idev, struct sk_buff *skb, u16 proto)
+{
+ unsigned char *p;
+
+ if (skb_headroom(skb) < 4) {
+ isdn_BUG();
+ return;
+ }
+
+ if ((idev->pppcfg & SC_COMP_PROT) && proto <= 0xff)
+ put_u8(skb_push(skb, 1), proto);
+ else
+ put_u16(skb_push(skb, 2), proto);
+
+ if (idev->pppcfg & SC_COMP_AC)
+ return;
+
+ p = skb_push(skb, 2);
+ p += put_u8(p, PPP_ALLSTATIONS);
+ p += put_u8(p, PPP_UI);
+}
+
/*
* unbind isdn_net_local <=> ippp-device
* note: it can happen, that we hangup/free the master before the slaves
@@ -857,23 +881,29 @@ isdn_ppp_cleanup(void)
*/
static int isdn_ppp_skip_ac(isdn_net_dev *idev, struct sk_buff *skb)
{
+ u8 val;
+
if (skb->len < 1)
return -1;
- if (skb->data[0] == 0xff) {
- if (skb->len < 2)
- return -1;
-
- if (skb->data[1] != 0x03)
- return -1;
-
- // skip address/control (AC) field
- skb_pull(skb, 2);
- } else {
+ get_u8(skb->data, &val);
+ if (val != PPP_ALLSTATIONS) {
+ /* if AC compression was not negotiated, but no AC present,
+ discard packet */
if (idev->pppcfg & SC_REJ_COMP_AC)
- // if AC compression was not negotiated, but used, discard packet
return -1;
+
+ return 0;
}
+ if (skb->len < 2)
+ return -1;
+
+ get_u8(skb->data + 1, &val);
+ if (val != PPP_UI)
+ return -1;
+
+ /* skip address/control (AC) field */
+ skb_pull(skb, 2);
return 0;
}
@@ -883,19 +913,21 @@ static int isdn_ppp_skip_ac(isdn_net_dev *idev, struct sk_buff *skb)
*/
int isdn_ppp_strip_proto(struct sk_buff *skb)
{
- int proto;
-
+ u16 proto;
+ u8 val;
+
if (skb->len < 1)
return -1;
- if (skb->data[0] & 0x1) {
- // protocol field is compressed
- proto = skb->data[0];
+ get_u8(skb->data, &val);
+ if (val & 0x1) {
+ /* protocol field is compressed */
+ proto = val;
skb_pull(skb, 1);
} else {
if (skb->len < 2)
return -1;
- proto = ((int) skb->data[0] << 8) + skb->data[1];
+ get_u16(skb->data, &proto);
skb_pull(skb, 2);
}
return proto;
@@ -911,13 +943,6 @@ static void isdn_ppp_receive(isdn_net_local *lp, isdn_net_dev *idev,
struct ipppd *is;
int proto;
- /*
- * If encapsulation is syncppp, don't reset
- * huptimer on LCP packets.
- */
- if (PPP_PROTOCOL(skb->data) != PPP_LCP)
- idev->huptimer = 0;
-
is = ipppd_get(idev->ppp_slot);
if (!is)
goto err;
@@ -934,6 +959,10 @@ static void isdn_ppp_receive(isdn_net_local *lp, isdn_net_dev *idev,
proto = isdn_ppp_strip_proto(skb);
if (proto < 0)
goto err_put;
+
+ /* Don't reset huptimer on LCP packets. */
+ if (proto != PPP_LCP)
+ idev->huptimer = 0;
#ifdef CONFIG_ISDN_MPP
if (is->compflags & SC_LINK_DECOMP_ON) {
@@ -1072,32 +1101,6 @@ isdn_ppp_push_higher(isdn_net_local *lp, isdn_net_dev *idev,
}
/*
- * isdn_ppp_skb_push ..
- * checks whether we have enough space at the beginning of the skb
- * and allocs a new SKB if necessary
- */
-static unsigned char *isdn_ppp_skb_push(struct sk_buff **skb_p,int len)
-{
- struct sk_buff *skb = *skb_p;
-
- if(skb_headroom(skb) < len) {
- struct sk_buff *nskb = skb_realloc_headroom(skb, len);
-
- if (!nskb) {
- printk(KERN_ERR "isdn_ppp_skb_push: can't realloc headroom!\n");
- dev_kfree_skb(skb);
- return NULL;
- }
- printk(KERN_DEBUG "isdn_ppp_skb_push:under %d %d\n",skb_headroom(skb),len);
- dev_kfree_skb(skb);
- *skb_p = nskb;
- return skb_push(nskb, len);
- }
- return skb_push(skb,len);
-}
-
-
-/*
* send ppp frame .. we expect a PIDCOMPressable proto --
* (here: currently always PPP_IP,PPP_VJC_COMP,PPP_VJC_UNCOMP)
*
@@ -1258,27 +1261,7 @@ isdn_ppp_start_xmit(struct sk_buff *skb, struct net_device *ndev)
skb = isdn_ppp_compress(skb,&proto,ipt,ipts,1);
#endif
- if ((idev->pppcfg & SC_COMP_PROT) && (proto <= 0xff)) {
- unsigned char *data = isdn_ppp_skb_push(&skb,1);
- if(!data)
- goto put2;
- data[0] = proto & 0xff;
- } else {
- unsigned char *data = isdn_ppp_skb_push(&skb,2);
- if(!data)
- goto put2;
- data[0] = (proto >> 8) & 0xff;
- data[1] = proto & 0xff;
- }
- if (!(idev->pppcfg & SC_COMP_AC)) {
- unsigned char *data = isdn_ppp_skb_push(&skb,2);
- if(!data)
- goto put2;
- data[0] = 0xff; /* All Stations */
- data[1] = 0x03; /* Unnumbered information */
- }
-
- /* tx-stats are now updated via BSENT-callback */
+ isdn_ppp_push_header(idev, skb, proto);
if (ipts->debug & 0x40) {
printk(KERN_DEBUG "skb xmit: len: %d\n", (int) skb->len);
@@ -1287,7 +1270,6 @@ isdn_ppp_start_xmit(struct sk_buff *skb, struct net_device *ndev)
isdn_net_writebuf_skb(idev, skb);
- put2:
ipppd_put(ipt);
put:
ipppd_put(ipts);
@@ -1966,24 +1948,19 @@ static void isdn_ppp_ccp_lp_kick_up(void *priv, unsigned int flags)
isdn_ppp_fill_rq(NULL, 0, PPP_COMP, idev->ppp_slot);
}
-/* Send a CCP Reset-Request or Reset-Ack directly from the kernel. This is
- getting that lengthy because there is no simple "send-this-frame-out"
- function above but every wrapper does a bit different. Hope I guess
- correct in this hack... */
+/* Send a CCP Reset-Request or Reset-Ack directly from the kernel. */
-static void isdn_ppp_ccp_xmit_reset(void *priv, int proto,
- unsigned char code, unsigned char id,
- unsigned char *data, int len)
+static void
+isdn_ppp_ccp_xmit_reset(void *priv, int proto, unsigned char code,
+ unsigned char id, unsigned char *data, int len)
{
isdn_net_dev *idev = priv;
struct sk_buff *skb;
unsigned char *p;
int hl;
- int cnt = 0;
- /* Alloc large enough skb */
hl = isdn_slot_hdrlen(idev->isdn_slot);
- skb = alloc_skb(len + hl + 16,GFP_ATOMIC);
+ skb = alloc_skb(len + hl + IPPP_MAX_HEADER, GFP_ATOMIC);
if(!skb) {
printk(KERN_WARNING
"ippp: CCP cannot send reset - out of memory\n");
@@ -1991,31 +1968,18 @@ static void isdn_ppp_ccp_xmit_reset(void *priv, int proto,
}
skb_reserve(skb, hl+16);
- /* We may need to stuff an address and control field first */
- if (!(idev->pppcfg & SC_COMP_AC)) {
- p = skb_put(skb, 2);
- *p++ = 0xff;
- *p++ = 0x03;
- }
+ isdn_ppp_push_header(idev, skb, proto);
- /* Stuff proto, code, id and length */
- p = skb_put(skb, 6);
- *p++ = (proto >> 8);
- *p++ = (proto & 0xff);
- *p++ = code;
- *p++ = id;
- cnt = 4 + len;
- *p++ = (cnt >> 8);
- *p++ = (cnt & 0xff);
-
- /* Now stuff remaining bytes */
- if(len) {
- p = skb_put(skb, len);
- memcpy(p, data, len);
- }
+ p = skb_put(skb, 4);
+ p += put_u8 (p, code);
+ p += put_u8 (p, id);
+ p += put_u16(p, len + 4);
+
+ if (len)
+ memcpy(skb_put(skb, len), data, len);
- /* skb is now ready for xmit */
- isdn_ppp_frame_log("ccp-xmit", skb->data, skb->len, 32, -1, idev->ppp_slot);
+ isdn_ppp_frame_log("ccp-xmit", skb->data, skb->len, 32, -1,
+ idev->ppp_slot);
isdn_net_write_super(idev, skb);
}