diff options
| author | Kai Germaschewski <kai@tp1.ruhr-uni-bochum.de> | 2002-10-16 01:25:06 -0500 |
|---|---|---|
| committer | Kai Germaschewski <kai@tp1.ruhr-uni-bochum.de> | 2002-10-16 01:25:06 -0500 |
| commit | cb35e72a1b0cb37f26579f0531aa4643f2cff40f (patch) | |
| tree | 9e992bc89295cffb2fc245bba5b600858fa03329 | |
| parent | d6b0306380285563841369945d20d3c31e08582b (diff) | |
ISDN/PPP: clean up ipppd_write() and ipppd_ioctl()
plus other small cleanups, in particular getting rid of
isdn_ppp_{receive,send}_ccp() and calling into the CCP code directly.
| -rw-r--r-- | drivers/isdn/i4l/isdn_ppp.c | 430 | ||||
| -rw-r--r-- | drivers/isdn/i4l/isdn_ppp.h | 2 |
2 files changed, 175 insertions, 257 deletions
diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c index 996ddcde7ac2..13395d86720a 100644 --- a/drivers/isdn/i4l/isdn_ppp.c +++ b/drivers/isdn/i4l/isdn_ppp.c @@ -21,12 +21,11 @@ #include "isdn_ppp_ccp.h" #include "isdn_net.h" -static void -isdn_ppp_send_ccp(isdn_net_dev *net_dev, isdn_net_local *lp, - struct sk_buff *skb); +static struct sk_buff * +isdn_ppp_dev_alloc_skb(void *priv, int len, int gfp_mask); static int -isdn_ppp_set_compressor(struct ipppd *is,struct isdn_ppp_comp_data *); +isdn_ppp_set_compressor(isdn_net_dev *idev, struct isdn_ppp_comp_data *); /* ====================================================================== */ /* IPPPD handling */ @@ -212,86 +211,66 @@ static ssize_t ipppd_write(struct file *file, const char *buf, size_t count, loff_t *off) { isdn_net_dev *idev; - struct ipppd *is; - int proto; - unsigned char protobuf[4]; + struct ipppd *ipppd; + struct sk_buff *skb; + char *p; int retval; + u16 proto; if (off != &file->f_pos) return -ESPIPE; - lock_kernel(); - - is = file->private_data; - - ipppd_debug(is, ""); + ipppd = file->private_data; + ipppd_debug(ipppd, "count = %d", count); - if (is->state != IPPPD_ST_CONNECTED) { + if (ipppd->state != IPPPD_ST_CONNECTED) { retval = -ENOTCONN; goto out; } - /* -> push it directly to the lowlevel interface */ - - idev = is->idev; - if (!idev) - printk(KERN_DEBUG "isdn_ppp_write: idev == NULL\n"); - else { - /* - * Don't reset huptimer for - * LCP packets. (Echo requests). - */ - if (copy_from_user(protobuf, buf, 4)) { - retval = -EFAULT; - goto out; - } - proto = PPP_PROTOCOL(protobuf); - if (proto != PPP_LCP) - idev->huptimer = 0; - - if (idev->isdn_slot < 0) { - retval = 0; - goto out; - } - if ((dev->drv[isdn_slot_driver(idev->isdn_slot)]->flags & DRV_FLAG_RUNNING)) { - unsigned short hl; - struct sk_buff *skb; - /* - * we need to reserve enought space in front of - * sk_buff. old call to dev_alloc_skb only reserved - * 16 bytes, now we are looking what the driver want - */ - hl = isdn_slot_hdrlen(idev->isdn_slot); - skb = alloc_skb(hl+count, GFP_ATOMIC); - if (!skb) { - printk(KERN_WARNING "isdn_ppp_write: out of memory!\n"); - retval = count; - goto out; - } - skb_reserve(skb, hl); - if (copy_from_user(skb_put(skb, count), buf, count)) - { - kfree_skb(skb); - retval = -EFAULT; - goto out; - } - if (is->debug & 0x40) { - printk(KERN_DEBUG "ppp xmit: len %d\n", (int) skb->len); - isdn_ppp_frame_log("xmit", skb->data, skb->len, 32,is->unit,-1); - } - - /* keeps CCP/compression states in sync */ - isdn_ppp_send_ccp(idev,idev->mlp,skb); - - /* FIXME: Somewhere we need protection against the - * queue growing too large */ - isdn_net_write_super(idev, skb); - } + idev = ipppd->idev; + if (!idev) { + isdn_BUG(); + retval = -ENODEV; + goto out; + } + /* Daemon needs to send at least full header, AC + proto */ + if (count < 4) { + retval = -EMSGSIZE; + goto out; + } + skb = isdn_ppp_dev_alloc_skb(idev, count, GFP_KERNEL); + if (!skb) { + retval = -ENOMEM; + goto out; + } + p = skb_put(skb, count); + if (copy_from_user(p, buf, count)) { + kfree_skb(skb); + retval = -EFAULT; + goto out; } + /* Don't reset huptimer for LCP packets. (Echo requests). */ + proto = PPP_PROTOCOL(p); + if (proto != PPP_LCP) + idev->huptimer = 0; + + /* Keeps CCP/compression states in sync */ + switch (proto) { + case PPP_CCP: + ippp_ccp_send_ccp(idev->mlp->ccp, skb); + break; + case PPP_CCPFRAG: + ippp_ccp_send_ccp(idev->ccp, skb); + break; + } + /* FIXME: Somewhere we need protection against the + * queue growing too large */ + isdn_net_write_super(idev, skb); + retval = count; out: - unlock_kernel(); return retval; } @@ -335,20 +314,18 @@ ipppd_poll(struct file *file, poll_table * wait) /* get_arg .. ioctl helper */ static int -get_arg(void *b, void *val, int len) +get_arg(unsigned long arg, void *val, int len) { - if (len <= 0) - len = sizeof(void *); - if (copy_from_user((void *) val, b, len)) + if (copy_from_user((void *) val, (void *) arg, len)) return -EFAULT; return 0; } /* set arg .. ioctl helper */ static int -set_arg(void *b, void *val,int len) +set_arg(unsigned long arg, void *val,int len) { - if (copy_to_user(b, (void *) val, len)) + if (copy_to_user((void *) arg, (void *) val, len)) return -EFAULT; return 0; } @@ -372,53 +349,78 @@ ipppd_ioctl(struct inode *ino, struct file *file, unsigned int cmd, switch (cmd) { case PPPIOCBUNDLE: #ifdef CONFIG_ISDN_MPP - if (!(is->state & IPPP_CONNECT)) - return -EINVAL; - if ((r = get_arg((void *) arg, &val, sizeof(val) ))) - return r; + if (is->state != IPPPD_ST_CONNECTED) { + r = -EINVAL; + break; + } + r = get_arg(arg, &val, sizeof(val)); + if (r) + break; + printk(KERN_DEBUG "iPPP-bundle: minor: %d, slave unit: %d, master unit: %d\n", - (int) is->minor, (int) is->unit, (int) val); - return isdn_ppp_bundle(is, val); + is->minor, is->unit, val); + r = isdn_ppp_bundle(is, val); #else - return -1; + r = -EINVAL; #endif break; case PPPIOCGUNIT: /* get ppp/isdn unit number */ - if ((r = set_arg((void *) arg, &is->unit, sizeof(is->unit) ))) - return r; + r = set_arg(arg, &is->unit, sizeof(is->unit)); break; + case PPPIOCGDEBUG: + r = set_arg(arg, &is->debug, sizeof(is->debug)); + break; + case PPPIOCSDEBUG: + r = get_arg(arg, &val, sizeof(val)); + if (r) + break; + is->debug = val; + if (idev) { + idev->debug = val; + idev->mlp->debug = val; + } + break; + case PPPIOCGCOMPRESSORS: + { + unsigned long protos[8]; + ippp_ccp_get_compressors(protos); + r = set_arg(arg, protos, sizeof(protos)); + break; + } + default: + r = -ENOTTY; + break; + } + + if (r != -ENOTTY) + goto out; + + if (!idev) { + r = -ENODEV; + goto out; + } + + switch (cmd) { case PPPIOCGIFNAME: - if(!idev) - return -EINVAL; - if ((r = set_arg((void *) arg, idev->name, strlen(idev->name)))) - return r; + r = set_arg(arg, idev->name, strlen(idev->name)+1); break; case PPPIOCGMPFLAGS: /* get configuration flags */ - if (!idev) - return -ENODEV; - if ((r = set_arg((void *) arg, &idev->mlp->mpppcfg, sizeof(idev->mlp->mpppcfg) ))) - return r; + r = set_arg(arg, &idev->mlp->mpppcfg, sizeof(idev->mlp->mpppcfg)); break; case PPPIOCSMPFLAGS: /* set configuration flags */ - if (!idev) - return -ENODEV; - if ((r = get_arg((void *) arg, &val, sizeof(val) ))) - return r; + r = get_arg(arg, &val, sizeof(val)); + if (r) + break; idev->mlp->mpppcfg = val; break; case PPPIOCGFLAGS: /* get configuration flags */ - if (!idev) - return -ENODEV; cfg = idev->pppcfg | ippp_ccp_get_flags(idev->ccp); - if ((r = set_arg((void *) arg, &cfg, sizeof(cfg) ))) - return r; + r = set_arg(arg, &cfg, sizeof(cfg)); break; case PPPIOCSFLAGS: /* set configuration flags */ - if (!idev) - return -ENODEV; - if ((r = get_arg((void *) arg, &val, sizeof(val) ))) { - return r; - } + r = get_arg(arg, &val, sizeof(val)); + if (r) + break; if ((val & SC_ENABLE_IP) && !(idev->pppcfg & SC_ENABLE_IP)) { idev->pppcfg = val; /* OK .. we are ready to send buffers */ @@ -428,19 +430,18 @@ ipppd_ioctl(struct inode *ino, struct file *file, unsigned int cmd, idev->pppcfg = val; break; case PPPIOCGIDLE: /* get idle time information */ - if (idev) { - struct ppp_idle pidle; - pidle.xmit_idle = pidle.recv_idle = idev->huptimer; - if ((r = set_arg((void *) arg, &pidle,sizeof(struct ppp_idle)))) - return r; - } + { + struct ppp_idle pidle; + pidle.xmit_idle = pidle.recv_idle = idev->huptimer; + r = set_arg(arg, &pidle,sizeof(pidle)); break; + } case PPPIOCSMRU: /* set receive unit size for PPP */ - if (!idev) - return -ENODEV; - if ((r = get_arg((void *) arg, &val, sizeof(val) ))) - return r; - return ippp_ccp_set_mru(idev->ccp, val); + r = get_arg(arg, &val, sizeof(val)); + if (r) + break; + r = ippp_ccp_set_mru(idev->ccp, val); + break; case PPPIOCSMPMRU: break; case PPPIOCSMPMTU: @@ -449,82 +450,61 @@ ipppd_ioctl(struct inode *ino, struct file *file, unsigned int cmd, case PPPIOCSMAXCID: /* set the maximum compression slot id */ { struct slcompress *sltmp; - - if (!idev) - return -ENODEV; - if ((r = get_arg((void *) arg, &val, sizeof(val) ))) - return r; + r = get_arg(arg, &val, sizeof(val)); + if (r) + break; val++; - if (is->debug & 0x1) - printk(KERN_DEBUG "ippp, ioctl: changed MAXCID to %ld\n", val); sltmp = slhc_init(16, val); if (!sltmp) { - printk(KERN_ERR "ippp, can't realloc slhc struct\n"); - return -ENOMEM; + r = -ENOMEM; + break; } if (idev->mlp->slcomp) slhc_free(idev->mlp->slcomp); idev->mlp->slcomp = sltmp; + r = 0; break; } #endif - case PPPIOCGDEBUG: - if ((r = set_arg((void *) arg, &is->debug, sizeof(is->debug) ))) - return r; - break; - case PPPIOCSDEBUG: - if ((r = get_arg((void *) arg, &val, sizeof(val) ))) - return r; - is->debug = val; - if (idev) { - idev->debug = val; - idev->mlp->debug = val; - } - break; - case PPPIOCGCOMPRESSORS: - { - unsigned long protos[8]; - - ippp_ccp_get_compressors(protos); - if ((r = set_arg((void *) arg,protos,8*sizeof(long) ))) - return r; - } - break; case PPPIOCSCOMPRESSOR: - if ((r = get_arg((void *) arg, &data, sizeof(struct isdn_ppp_comp_data)))) - return r; - return isdn_ppp_set_compressor(is, &data); + r = get_arg(arg, &data, sizeof(data)); + if (r) + break; + r = isdn_ppp_set_compressor(idev, &data); + break; case PPPIOCGCALLINFO: { isdn_net_local *mlp; struct isdn_net_phone *phone; struct pppcallinfo pci; int i; - memset((char *) &pci,0,sizeof(struct pppcallinfo)); - if(idev) { - mlp = idev->mlp; - strncpy(pci.local_num, mlp->msn, 63); - i = 0; - list_for_each_entry(phone, &mlp->phone[1], list) { - if (i++ == idev->dial) { - strncpy(pci.remote_num,phone->num,63); - break; - } + memset(&pci, 0, sizeof(pci)); + + mlp = idev->mlp; + strncpy(pci.local_num, mlp->msn, 63); + i = 0; + list_for_each_entry(phone, &mlp->phone[1], list) { + if (i++ == idev->dial) { + strncpy(pci.remote_num,phone->num,63); + break; } - pci.charge_units = idev->charge; - if(idev->outgoing) - pci.calltype = CALLTYPE_OUTGOING; - else - pci.calltype = CALLTYPE_INCOMING; - if(mlp->flags & ISDN_NET_CALLBACK) - pci.calltype |= CALLTYPE_CALLBACK; } - return set_arg((void *)arg,&pci,sizeof(struct pppcallinfo)); + pci.charge_units = idev->charge; + if (idev->outgoing) + pci.calltype = CALLTYPE_OUTGOING; + else + pci.calltype = CALLTYPE_INCOMING; + if (mlp->flags & ISDN_NET_CALLBACK) + pci.calltype |= CALLTYPE_CALLBACK; + r = set_arg(arg, &pci, sizeof(pci)); + break; } default: + r = -ENOTTY; break; } - return 0; + out: + return r; } /* --- fops ------------------------------------------------------------- */ @@ -590,13 +570,6 @@ static void isdn_ppp_push_higher(isdn_net_local *lp, isdn_net_dev *idev, static int isdn_ppp_if_get_unit(char *namebuf); static void -isdn_ppp_receive_ccp(isdn_net_dev * net_dev, isdn_net_local * lp, - struct sk_buff *skb,int proto); - -static struct sk_buff * -isdn_ppp_dev_alloc_skb(void *priv, int len, int gfp_mask); - -static void isdn_ppp_dev_push_header(void *priv, struct sk_buff *skb, u16 proto); static void @@ -934,7 +907,6 @@ int isdn_ppp_strip_proto(struct sk_buff *skb) return proto; } - /* * handler for incoming packets on a syncPPP interface */ @@ -1060,22 +1032,22 @@ isdn_ppp_push_higher(isdn_net_local *lp, isdn_net_dev *idev, } break; #endif - case PPP_CCP: case PPP_CCPFRAG: - isdn_ppp_receive_ccp(idev,lp,skb,proto); + ippp_ccp_receive_ccp(idev->ccp, skb); + goto ccp; + case PPP_CCP: + ippp_ccp_receive_ccp(lp->ccp, skb); + ccp: /* Dont pop up ResetReq/Ack stuff to the daemon any longer - the job is done already */ if(skb->data[0] == CCP_RESETREQ || - skb->data[0] == CCP_RESETACK) { - kfree_skb(skb); - goto out; - } + skb->data[0] == CCP_RESETACK) + goto free; /* fall through */ default: // FIXME use skb directly ipppd_queue_read(is, proto, skb->data, skb->len); - kfree_skb(skb); - goto out; + goto free; } /* Reset hangup-timer */ @@ -1089,6 +1061,7 @@ isdn_ppp_push_higher(isdn_net_local *lp, isdn_net_dev *idev, drop: lp->stats.rx_dropped++; + free: kfree_skb(skb); } @@ -1795,17 +1768,18 @@ isdn_ppp_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) return -EINVAL; switch (cmd) { - case SIOCGPPPVER: - r = (char *) ifr->ifr_ifru.ifru_data; - len = strlen(PPP_VERSION) + 1; - if(copy_to_user(r, PPP_VERSION, len)) error = -EFAULT; - break; - case SIOCGPPPSTATS: - error = isdn_ppp_dev_ioctl_stats(ifr, dev); - break; - default: - error = -EINVAL; - break; + case SIOCGPPPVER: + r = (char *) ifr->ifr_ifru.ifru_data; + len = strlen(PPP_VERSION) + 1; + if (copy_to_user(r, PPP_VERSION, len)) + error = -EFAULT; + break; + case SIOCGPPPSTATS: + error = isdn_ppp_dev_ioctl_stats(ifr, dev); + break; + default: + error = -EINVAL; + break; } return error; } @@ -2001,72 +1975,17 @@ isdn_ppp_lp_xmit(void *priv, struct sk_buff *skb) isdn_net_write_super(idev, skb); } - -/* - * we received a CCP frame .. - * not a clean solution, but we MUST handle a few cases in the kernel - */ -static void -isdn_ppp_receive_ccp(isdn_net_dev *idev, isdn_net_local *lp, - struct sk_buff *skb,int proto) -{ - if (proto == PPP_CCP) - ippp_ccp_receive_ccp(lp->ccp, skb); - else - ippp_ccp_receive_ccp(idev->ccp, skb); -} - - -/* - * Daemon sends a CCP frame ... - */ - -static void isdn_ppp_send_ccp(isdn_net_dev *idev, isdn_net_local *lp, struct sk_buff *skb) -{ - int proto; - unsigned char *data; - - if (!skb || skb->len < 3) { - isdn_BUG(); - return; - } - /* Daemon may send with or without address and control field comp */ - data = skb->data; - if (data[0] == 0xff && data[1] == 0x03) { - data += 2; - if(skb->len < 5) - return; - } - proto = ((int)data[0]<<8)+data[1]; - - switch (proto) { - case PPP_CCP: - ippp_ccp_send_ccp(lp->ccp, skb); - break; - case PPP_CCPFRAG: - ippp_ccp_send_ccp(idev->ccp, skb); - break; - } -} - static int -isdn_ppp_set_compressor(struct ipppd *is, struct isdn_ppp_comp_data *data) +isdn_ppp_set_compressor(isdn_net_dev *idev, struct isdn_ppp_comp_data *data) { - isdn_net_dev *idev = is->idev; - isdn_net_local *lp; struct ippp_ccp *ccp; - if (!idev) - return -ENODEV; - - lp = idev->mlp; - if (data->flags & IPPP_COMP_FLAG_LINK) ccp = idev->ccp; else - ccp = lp->ccp; + ccp = idev->mlp->ccp; - return ippp_ccp_set_compressor(ccp, is->unit, data); + return ippp_ccp_set_compressor(ccp, idev->ipppd->unit, data); } // ISDN_NET_ENCAP_SYNCPPP @@ -2102,6 +2021,7 @@ isdn_ppp_close(isdn_net_local *lp) lp->slcomp = NULL; #endif ippp_ccp_free(lp->ccp); + lp->ccp = NULL; } struct isdn_netif_ops isdn_ppp_ops = { diff --git a/drivers/isdn/i4l/isdn_ppp.h b/drivers/isdn/i4l/isdn_ppp.h index 3509e8a54f5b..20745b31ef1d 100644 --- a/drivers/isdn/i4l/isdn_ppp.h +++ b/drivers/isdn/i4l/isdn_ppp.h @@ -27,5 +27,3 @@ int isdn_ppp_strip_proto(struct sk_buff *skb); #define IPPP_MAX_HEADER 10 - - |
