2460 lines
118 KiB
Plaintext
2460 lines
118 KiB
Plaintext
<HTML>
|
|
|
|
<!-- Generated by c2html-1.0, Copyright 1998 by Dave Whittington -->
|
|
<HEAD>
|
|
<TITLE>isdn_ppp.c</TITLE>
|
|
<!--#include virtual="/ssi/js.shtml" -->
|
|
<!--#include virtual="/ssi/buttondefs.shtml" -->
|
|
</HEAD>
|
|
<BODY BGCOLOR="#FFFFFF">
|
|
<TABLE WIDTH="100%">
|
|
<TR>
|
|
<TD ALIGN=LEFT WIDTH="90"><!--#include virtual="/ssi/b_home.shtml" --></TD>
|
|
<TD ALIGN=RIGHT WIDTH="90"><!--#include virtual="/ssi/b_index.shtml" --></TD>
|
|
</TR>
|
|
</TABLE>
|
|
<CENTER><H1>isdn_ppp.c</H1></CENTER>
|
|
|
|
<HR>
|
|
<PRE>
|
|
<FONT COLOR=#0000FF>/* $Id$
|
|
*
|
|
* Linux ISDN subsystem, functions for synchronous PPP (linklevel).
|
|
*
|
|
* Copyright 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2, or (at your option)
|
|
* any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*
|
|
* $Log$
|
|
* Revision 1.40 1998/04/06 19:07:27 hipp
|
|
* added check, whether compression is enabled.
|
|
*
|
|
* Revision 1.39 1998/03/25 22:46:53 hipp
|
|
* Some additional CCP changes.
|
|
*
|
|
* Revision 1.38 1998/03/24 16:33:06 hipp
|
|
* More CCP changes. BSD compression now "works" on a local loopback link.
|
|
* Moved some isdn_ppp stuff from isdn.h to isdn_ppp.h
|
|
*
|
|
* Revision 1.37 1998/03/22 18:50:49 hipp
|
|
* Added BSD Compression for syncPPP .. UNTESTED at the moment
|
|
*
|
|
* Revision 1.36 1998/03/09 17:46:30 he
|
|
* merged in 2.1.89 changes
|
|
*
|
|
* Revision 1.35 1998/03/07 18:21:11 cal
|
|
* Dynamic Timeout-Rule-Handling vs. 971110 included
|
|
*
|
|
* Revision 1.34 1998/02/25 17:49:48 he
|
|
* Changed return codes caused be failing copy_{to,from}_user to -EFAULT
|
|
*
|
|
* Revision 1.33 1998/02/20 17:11:54 fritz
|
|
* Changes for recent kernels.
|
|
*
|
|
* Revision 1.32 1998/01/31 19:29:55 calle
|
|
* Merged changes from and for 2.1.82, not tested only compiled ...
|
|
*
|
|
* Revision 1.31 1997/10/09 21:29:01 fritz
|
|
* New HL<->LL interface:
|
|
* New BSENT callback with nr. of bytes included.
|
|
* Sending without ACK.
|
|
* New L1 error status (not yet in use).
|
|
* Cleaned up obsolete structures.
|
|
* Implemented Cisco-SLARP.
|
|
* Changed local net-interface data to be dynamically allocated.
|
|
* Removed old 2.0 compatibility stuff.
|
|
*
|
|
* Revision 1.30 1997/10/01 09:20:38 fritz
|
|
* Removed old compatibility stuff for 2.0.X kernels.
|
|
* From now on, this code is for 2.1.X ONLY!
|
|
* Old stuff is still in the separate branch.
|
|
*
|
|
* Revision 1.29 1997/08/21 23:11:44 fritz
|
|
* Added changes for kernels >= 2.1.45
|
|
*
|
|
* Revision 1.28 1997/06/17 13:05:57 hipp
|
|
* Applied Eric's underflow-patches (slightly modified)
|
|
* more compression changes (but disabled at the moment)
|
|
* changed one copy_to_user() to run with enabled IRQs
|
|
* a few MP changes
|
|
* changed 'proto' handling in the isdn_ppp receive code
|
|
*
|
|
* Revision 1.27 1997/03/30 16:51:17 calle
|
|
* changed calls to copy_from_user/copy_to_user and removed verify_area
|
|
* were possible.
|
|
*
|
|
* Revision 1.26 1997/02/23 16:53:44 hipp
|
|
* minor cleanup
|
|
* some initial changes for future PPP compresion
|
|
* added AC,PC compression for outgoing frames
|
|
*
|
|
* Revision 1.25 1997/02/12 20:37:35 hipp
|
|
* New ioctl() PPPIOCGCALLINFO, minor cleanup
|
|
*
|
|
* Revision 1.24 1997/02/11 18:32:56 fritz
|
|
* Bugfix in isdn_ppp_free_mpqueue().
|
|
*
|
|
* Revision 1.23 1997/02/10 11:12:19 fritz
|
|
* More changes for Kernel 2.1.X compatibility.
|
|
*
|
|
* Revision 1.22 1997/02/06 15:03:51 hipp
|
|
* changed GFP_KERNEL kmalloc to GFP_ATOMIC in isdn_ppp_fill_mpqueue()
|
|
*
|
|
* Revision 1.21 1997/02/03 23:29:38 fritz
|
|
* Reformatted according CodingStyle
|
|
* Bugfix: removed isdn_ppp_skb_destructor, used by upper layers.
|
|
* Misc changes for Kernel 2.1.X compatibility.
|
|
*
|
|
* Revision 1.20 1996/10/30 12:21:58 fritz
|
|
* Cosmetic fix: Compiler warning when compiling without MPP.
|
|
*
|
|
* Revision 1.19 1996/10/25 19:03:21 hipp
|
|
* changed/added some defines to (re)allow compilation without MP/VJ
|
|
*
|
|
* Revision 1.18 1996/10/22 23:14:00 fritz
|
|
* Changes for compatibility to 2.0.X and 2.1.X kernels.
|
|
*
|
|
* Revision 1.17 1996/10/22 09:39:49 hipp
|
|
* a few MP changes and bugfixes
|
|
*
|
|
* Revision 1.16 1996/09/23 01:58:10 fritz
|
|
* Fix: With syncPPP encapsulation, discard LCP packets
|
|
* when calculating hangup timeout.
|
|
*
|
|
* Revision 1.15 1996/09/07 12:50:12 hipp
|
|
* bugfixes (unknown device after failed dial attempt, minor bugs)
|
|
*
|
|
* Revision 1.14 1996/08/12 16:26:47 hipp
|
|
* code cleanup
|
|
* changed connection management from minors to slots
|
|
*
|
|
* Revision 1.13 1996/07/01 19:47:24 hipp
|
|
* Fixed memory leak in VJ handling and more VJ changes
|
|
*
|
|
* Revision 1.12 1996/06/24 17:42:03 fritz
|
|
* Minor bugfixes.
|
|
*
|
|
* Revision 1.11 1996/06/16 17:46:05 tsbogend
|
|
* changed unsigned long to u32 to make Alpha people happy
|
|
*
|
|
* Revision 1.10 1996/06/11 14:50:29 hipp
|
|
* Lot of changes and bugfixes.
|
|
* New scheme to resend packets to busy LL devices.
|
|
*
|
|
* Revision 1.9 1996/05/18 01:37:01 fritz
|
|
* Added spelling corrections and some minor changes
|
|
* to stay in sync with kernel.
|
|
*
|
|
* Revision 1.8 1996/05/06 11:34:55 hipp
|
|
* fixed a few bugs
|
|
*
|
|
* Revision 1.7 1996/04/30 11:07:42 fritz
|
|
* Added Michael's ippp-bind patch.
|
|
*
|
|
* Revision 1.6 1996/04/30 09:33:09 fritz
|
|
* Removed compatibility-macros.
|
|
*
|
|
* Revision 1.5 1996/04/20 16:32:32 fritz
|
|
* Changed ippp_table to an array of pointers, allocating each part
|
|
* separately.
|
|
*
|
|
* Revision 1.4 1996/02/19 15:25:50 fritz
|
|
* Bugfix: Sync-PPP packets got compressed twice, when resent due to
|
|
* send-queue-full reject.
|
|
*
|
|
* Revision 1.3 1996/02/11 02:27:12 fritz
|
|
* Lot of Bugfixes my Michael.
|
|
* Moved calls to skb_push() into isdn_net_header()
|
|
* Fixed a possible race-condition in isdn_ppp_timer_timeout().
|
|
*
|
|
* Revision 1.2 1996/01/22 05:08:06 fritz
|
|
* Merged in Michael's patches for MP.
|
|
* Minor changes in isdn_ppp_xmit.
|
|
*
|
|
* Revision 1.1 1996/01/09 04:11:29 fritz
|
|
* Initial revision
|
|
*
|
|
*/</FONT>
|
|
|
|
<FONT COLOR=#0000FF>/* TODO: right tbusy handling when using MP */</FONT>
|
|
|
|
<FONT COLOR=#0000FF>/*
|
|
* experimental for dynamic addressing: readdress IP frames
|
|
*/</FONT>
|
|
<FONT COLOR=#A521F7>#undef</FONT> ISDN_SYNCPPP_READDRESS
|
|
<FONT COLOR=#A521F7>#define</FONT> <A NAME="CONFIG_ISDN_CCP">CONFIG_ISDN_CCP</A> 1
|
|
|
|
<FONT COLOR=#A521F7>#include</FONT> <linux/config.h>
|
|
<FONT COLOR=#A521F7>#define</FONT> <A HREF="isdn_audio.c.shtml#__NO_VERSION__">__NO_VERSION__</A>
|
|
<FONT COLOR=#A521F7>#include</FONT> <linux/module.h>
|
|
<FONT COLOR=#A521F7>#include</FONT> <linux/version.h>
|
|
<FONT COLOR=#A521F7>#include</FONT> <linux/poll.h>
|
|
<FONT COLOR=#A521F7>#include</FONT> <linux/isdn.h>
|
|
<FONT COLOR=#A521F7>#include</FONT> <linux/ppp-comp.h>
|
|
|
|
<FONT COLOR=#A521F7>#include</FONT> <FONT COLOR="#FF0000">"isdn_common.h"</FONT>
|
|
<FONT COLOR=#A521F7>#include</FONT> <FONT COLOR="#FF0000">"isdn_ppp.h"</FONT>
|
|
<FONT COLOR=#A521F7>#include</FONT> <FONT COLOR="#FF0000">"isdn_net.h"</FONT>
|
|
|
|
<FONT COLOR=#A521F7>#ifndef</FONT> <A HREF="#PPP_IPX">PPP_IPX</A>
|
|
<FONT COLOR=#A521F7>#define</FONT> <A NAME="PPP_IPX">PPP_IPX</A> 0x002b
|
|
<FONT COLOR=#A521F7>#endif</FONT>
|
|
|
|
<FONT COLOR=#0000FF>/* set this if you use dynamic addressing */</FONT>
|
|
|
|
<FONT COLOR=#0000FF>/* Prototypes */</FONT>
|
|
<FONT COLOR="#298C52">static</FONT> <FONT COLOR="#298C52">int</FONT> <A HREF="#isdn_ppp_fill_rq">isdn_ppp_fill_rq</A>(<FONT COLOR="#298C52">unsigned</FONT> <FONT COLOR="#298C52">char</FONT> *buf, <FONT COLOR="#298C52">int</FONT> len, <FONT COLOR="#298C52">int</FONT> proto, <FONT COLOR="#298C52">int</FONT> slot);
|
|
<FONT COLOR="#298C52">static</FONT> <FONT COLOR="#298C52">int</FONT> <A HREF="#isdn_ppp_closewait">isdn_ppp_closewait</A>(<FONT COLOR="#298C52">int</FONT> slot);
|
|
<FONT COLOR="#298C52">static</FONT> <FONT COLOR="#298C52">void</FONT> <A HREF="#isdn_ppp_push_higher">isdn_ppp_push_higher</A>(<A HREF="../includes/isdn.h.shtml#isdn_net_dev">isdn_net_dev</A> * net_dev, isdn_net_local * lp,
|
|
<FONT COLOR="#298C52">struct</FONT> sk_buff *skb, <FONT COLOR="#298C52">int</FONT> proto);
|
|
<FONT COLOR="#298C52">static</FONT> <FONT COLOR="#298C52">int</FONT> <A HREF="#isdn_ppp_if_get_unit">isdn_ppp_if_get_unit</A>(<FONT COLOR="#298C52">char</FONT> *namebuf);
|
|
<FONT COLOR="#298C52">static</FONT> <FONT COLOR="#298C52">int</FONT> <A HREF="#isdn_ppp_set_compressor">isdn_ppp_set_compressor</A>(<FONT COLOR="#298C52">struct</FONT> ippp_struct *is,<FONT COLOR="#298C52">struct</FONT> isdn_ppp_comp_data *);
|
|
<FONT COLOR="#298C52">static</FONT> <FONT COLOR="#298C52">struct</FONT> sk_buff *<A HREF="#isdn_ppp_decompress">isdn_ppp_decompress</A>(<FONT COLOR="#298C52">struct</FONT> sk_buff *,
|
|
<FONT COLOR="#298C52">struct</FONT> ippp_struct *,<FONT COLOR="#298C52">struct</FONT> ippp_struct *,<FONT COLOR="#298C52">int</FONT> proto);
|
|
<FONT COLOR="#298C52">static</FONT> <FONT COLOR="#298C52">void</FONT> <A HREF="#isdn_ppp_receive_ccp">isdn_ppp_receive_ccp</A>(<A HREF="../includes/isdn.h.shtml#isdn_net_dev">isdn_net_dev</A> * net_dev, isdn_net_local * lp,
|
|
<FONT COLOR="#298C52">struct</FONT> sk_buff *skb,<FONT COLOR="#298C52">int</FONT> proto);
|
|
<FONT COLOR="#298C52">static</FONT> <FONT COLOR="#298C52">struct</FONT> sk_buff *<A HREF="#isdn_ppp_compress">isdn_ppp_compress</A>(<FONT COLOR="#298C52">struct</FONT> sk_buff *skb_in,<FONT COLOR="#298C52">int</FONT> *proto,
|
|
<FONT COLOR="#298C52">struct</FONT> ippp_struct *is,<FONT COLOR="#298C52">struct</FONT> ippp_struct *master,<FONT COLOR="#298C52">int</FONT> type);
|
|
<FONT COLOR="#298C52">static</FONT> <FONT COLOR="#298C52">void</FONT> <A HREF="#isdn_ppp_send_ccp">isdn_ppp_send_ccp</A>(<A HREF="../includes/isdn.h.shtml#isdn_net_dev">isdn_net_dev</A> *net_dev, isdn_net_local *lp,
|
|
<FONT COLOR="#298C52">struct</FONT> sk_buff *skb);
|
|
|
|
<FONT COLOR=#A521F7>#ifdef</FONT> CONFIG_ISDN_MPP
|
|
<FONT COLOR="#298C52">static</FONT> <FONT COLOR="#298C52">int</FONT> <A HREF="#isdn_ppp_bundle">isdn_ppp_bundle</A>(<FONT COLOR="#298C52">struct</FONT> ippp_struct *, <FONT COLOR="#298C52">int</FONT> unit);
|
|
<FONT COLOR="#298C52">static</FONT> <FONT COLOR="#298C52">void</FONT> <A HREF="#isdn_ppp_mask_queue">isdn_ppp_mask_queue</A>(<A HREF="../includes/isdn.h.shtml#isdn_net_dev">isdn_net_dev</A> * dev, <FONT COLOR="#298C52">long</FONT> mask);
|
|
<FONT COLOR="#298C52">static</FONT> <FONT COLOR="#298C52">void</FONT> <A HREF="#isdn_ppp_cleanup_mpqueue">isdn_ppp_cleanup_mpqueue</A>(<A HREF="../includes/isdn.h.shtml#isdn_net_dev">isdn_net_dev</A> * dev, <FONT COLOR="#298C52">long</FONT> min);
|
|
<FONT COLOR="#298C52">static</FONT> <FONT COLOR="#298C52">void</FONT> <A HREF="#isdn_ppp_cleanup_sqqueue">isdn_ppp_cleanup_sqqueue</A>(<A HREF="../includes/isdn.h.shtml#isdn_net_dev">isdn_net_dev</A> * dev, isdn_net_local *, <FONT COLOR="#298C52">long</FONT> min);
|
|
<FONT COLOR="#298C52">static</FONT> <FONT COLOR="#298C52">void</FONT> <A HREF="#isdn_ppp_free_sqqueue">isdn_ppp_free_sqqueue</A>(<A HREF="../includes/isdn.h.shtml#isdn_net_dev">isdn_net_dev</A> *);
|
|
<FONT COLOR="#298C52">static</FONT> <FONT COLOR="#298C52">int</FONT> <A HREF="#isdn_ppp_fill_mpqueue">isdn_ppp_fill_mpqueue</A>(<A HREF="../includes/isdn.h.shtml#isdn_net_dev">isdn_net_dev</A> *, <FONT COLOR="#298C52">struct</FONT> sk_buff **skb,
|
|
<FONT COLOR="#298C52">int</FONT> BEbyte, <FONT COLOR="#298C52">long</FONT> *sqno, <FONT COLOR="#298C52">int</FONT> min_sqno);
|
|
<FONT COLOR="#298C52">static</FONT> <FONT COLOR="#298C52">void</FONT> <A HREF="#isdn_ppp_free_mpqueue">isdn_ppp_free_mpqueue</A>(<A HREF="../includes/isdn.h.shtml#isdn_net_dev">isdn_net_dev</A> *);
|
|
<FONT COLOR=#A521F7>#endif</FONT>
|
|
|
|
<FONT COLOR="#298C52">char</FONT> *isdn_ppp_revision = <FONT COLOR="#FF0000">"$Revision$"</FONT>;
|
|
|
|
<FONT COLOR="#298C52">static</FONT> <FONT COLOR="#298C52">struct</FONT> ippp_struct *ippp_table[<A HREF="../includes/isdn.h.shtml#ISDN_MAX_CHANNELS">ISDN_MAX_CHANNELS</A>];
|
|
<FONT COLOR="#298C52">static</FONT> <FONT COLOR="#298C52">struct</FONT> isdn_ppp_compressor *ipc_head = NULL;
|
|
|
|
<FONT COLOR="#298C52">extern</FONT> <FONT COLOR="#298C52">int</FONT> <A HREF="isdn_net.c.shtml#isdn_net_force_dial_lp">isdn_net_force_dial_lp</A>(isdn_net_local *);
|
|
|
|
<FONT COLOR=#0000FF>/*
|
|
* frame log (debug)
|
|
*/</FONT>
|
|
<FONT COLOR="#298C52">static</FONT> <FONT COLOR="#298C52">void</FONT>
|
|
<A HREF="#isdn_ppp_frame_log">isdn_ppp_frame_log</A>(<FONT COLOR="#298C52">char</FONT> *info, <FONT COLOR="#298C52">char</FONT> *data, <FONT COLOR="#298C52">int</FONT> len, <FONT COLOR="#298C52">int</FONT> maxlen,<FONT COLOR="#298C52">int</FONT> unit)
|
|
{
|
|
<FONT COLOR="#298C52">int</FONT> cnt,
|
|
j,
|
|
i;
|
|
<FONT COLOR="#298C52">char</FONT> buf[80];
|
|
|
|
<FONT COLOR="#298C52">if</FONT> (len < maxlen)
|
|
maxlen = len;
|
|
|
|
<FONT COLOR="#298C52">for</FONT> (i = 0, cnt = 0; cnt < maxlen; i++) {
|
|
<FONT COLOR="#298C52">for</FONT> (j = 0; j < 16 && cnt < maxlen; j++, cnt++)
|
|
sprintf(buf + j * 3, <FONT COLOR="#FF0000">"%02x "</FONT>, (<FONT COLOR="#298C52">unsigned</FONT> <FONT COLOR="#298C52">char</FONT>) data[cnt]);
|
|
printk(KERN_DEBUG <FONT COLOR="#FF0000">"[%d].%s[%d]: %s\n"</FONT>,unit, info, i, buf);
|
|
}
|
|
}
|
|
|
|
<FONT COLOR=#0000FF>/*
|
|
* unbind isdn_net_local <=> ippp-device
|
|
* note: it can happen, that we hangup/free the master before the slaves
|
|
* in this case we bind another lp to the master device
|
|
*/</FONT>
|
|
<FONT COLOR="#298C52">int</FONT>
|
|
<A NAME="isdn_ppp_free">isdn_ppp_free</A>(isdn_net_local * lp)
|
|
{
|
|
<FONT COLOR=#A521F7>#ifdef</FONT> CONFIG_ISDN_MPP
|
|
isdn_net_local *master_lp = lp;
|
|
<FONT COLOR=#A521F7>#endif</FONT>
|
|
<FONT COLOR="#298C52">unsigned</FONT> <FONT COLOR="#298C52">long</FONT> flags;
|
|
<FONT COLOR="#298C52">struct</FONT> ippp_struct *is;
|
|
|
|
<FONT COLOR="#298C52">if</FONT> (lp->ppp_slot < 0 || lp->ppp_slot > <A HREF="../includes/isdn.h.shtml#ISDN_MAX_CHANNELS">ISDN_MAX_CHANNELS</A>)
|
|
<FONT COLOR="#298C52">return</FONT> 0;
|
|
|
|
is = ippp_table[lp->ppp_slot];
|
|
|
|
save_flags(flags);
|
|
<A HREF="kdebug.h.shtml#cli">cli</A>();
|
|
<FONT COLOR=#A521F7>#ifdef</FONT> CONFIG_ISDN_MPP
|
|
<FONT COLOR="#298C52">if</FONT> (lp->master)
|
|
master_lp = (isdn_net_local *) lp->master->priv;
|
|
|
|
lp->last->next = lp->next;
|
|
lp->next->last = lp->last;
|
|
<FONT COLOR="#298C52">if</FONT> (master_lp->netdev->queue == lp) {
|
|
master_lp->netdev->queue = lp->next;
|
|
<FONT COLOR="#298C52">if</FONT> (lp->next == lp) { <FONT COLOR=#0000FF>/* last link in queue? */</FONT>
|
|
master_lp->netdev->ib.bundled = 0;
|
|
<A HREF="#isdn_ppp_free_mpqueue">isdn_ppp_free_mpqueue</A>(master_lp->netdev);
|
|
<A HREF="#isdn_ppp_free_sqqueue">isdn_ppp_free_sqqueue</A>(master_lp->netdev);
|
|
}
|
|
}
|
|
lp->next = lp->last = lp; <FONT COLOR=#0000FF>/* (re)set own pointers */</FONT>
|
|
<FONT COLOR=#A521F7>#endif</FONT>
|
|
|
|
<FONT COLOR="#298C52">if</FONT> ((is->state & <A HREF="isdn_ppp.h.shtml#IPPP_CONNECT">IPPP_CONNECT</A>))
|
|
<A HREF="#isdn_ppp_closewait">isdn_ppp_closewait</A>(lp->ppp_slot); <FONT COLOR=#0000FF>/* force wakeup on ippp device */</FONT>
|
|
<FONT COLOR="#298C52">else</FONT> <FONT COLOR="#298C52">if</FONT> (is->state & <A HREF="isdn_ppp.h.shtml#IPPP_ASSIGNED">IPPP_ASSIGNED</A>)
|
|
is->state = <A HREF="isdn_ppp.h.shtml#IPPP_OPEN">IPPP_OPEN</A>; <FONT COLOR=#0000FF>/* fallback to 'OPEN but not ASSIGEND' state */</FONT>
|
|
|
|
<FONT COLOR="#298C52">if</FONT> (is->debug & 0x1)
|
|
printk(KERN_DEBUG <FONT COLOR="#FF0000">"isdn_ppp_free %d %lx %lx\n"</FONT>, lp->ppp_slot, (<FONT COLOR="#298C52">long</FONT>) lp, (<FONT COLOR="#298C52">long</FONT>) is->lp);
|
|
|
|
is->lp = NULL; <FONT COLOR=#0000FF>/* link is down .. set lp to NULL */</FONT>
|
|
<FONT COLOR=#A521F7>#ifdef</FONT> ISDN_SYNCPPP_READDRESS
|
|
is->old_pa_addr = 0x0;
|
|
is->old_pa_dstaddr = 0x0;
|
|
<FONT COLOR=#A521F7>#endif</FONT>
|
|
lp->ppp_slot = -1; <FONT COLOR=#0000FF>/* is this OK ?? */</FONT>
|
|
<A HREF="kdebug.h.shtml#restore_flags">restore_flags</A>(flags);
|
|
|
|
<FONT COLOR="#298C52">return</FONT> 0;
|
|
}
|
|
|
|
<FONT COLOR=#0000FF>/*
|
|
* bind isdn_net_local <=> ippp-device
|
|
*/</FONT>
|
|
<FONT COLOR="#298C52">int</FONT>
|
|
<A NAME="isdn_ppp_bind">isdn_ppp_bind</A>(isdn_net_local * lp)
|
|
{
|
|
<FONT COLOR="#298C52">int</FONT> i;
|
|
<FONT COLOR="#298C52">int</FONT> unit = 0;
|
|
<FONT COLOR="#298C52">long</FONT> flags;
|
|
<FONT COLOR="#298C52">struct</FONT> ippp_struct *is;
|
|
|
|
<FONT COLOR="#298C52">if</FONT> (lp->p_encap != <A HREF="../includes/isdn.h.shtml#ISDN_NET_ENCAP_SYNCPPP">ISDN_NET_ENCAP_SYNCPPP</A>)
|
|
<FONT COLOR="#298C52">return</FONT> -1;
|
|
|
|
save_flags(flags);
|
|
<A HREF="kdebug.h.shtml#cli">cli</A>();
|
|
|
|
<FONT COLOR="#298C52">if</FONT> (lp->pppbind < 0) { <FONT COLOR=#0000FF>/* device bounded to ippp device ? */</FONT>
|
|
<A HREF="../includes/isdn.h.shtml#isdn_net_dev">isdn_net_dev</A> *net_dev = dev->netdev;
|
|
<FONT COLOR="#298C52">char</FONT> exclusive[<A HREF="../includes/isdn.h.shtml#ISDN_MAX_CHANNELS">ISDN_MAX_CHANNELS</A>]; <FONT COLOR=#0000FF>/* exclusive flags */</FONT>
|
|
memset(exclusive, 0, <A HREF="../includes/isdn.h.shtml#ISDN_MAX_CHANNELS">ISDN_MAX_CHANNELS</A>);
|
|
<FONT COLOR="#298C52">while</FONT> (net_dev) { <FONT COLOR=#0000FF>/* step through net devices to find exclusive minors */</FONT>
|
|
isdn_net_local *lp = net_dev->local;
|
|
<FONT COLOR="#298C52">if</FONT> (lp->pppbind >= 0)
|
|
exclusive[lp->pppbind] = 1;
|
|
net_dev = net_dev->next;
|
|
}
|
|
<FONT COLOR=#0000FF>/*
|
|
* search a free device / slot
|
|
*/</FONT>
|
|
<FONT COLOR="#298C52">for</FONT> (i = 0; i < <A HREF="../includes/isdn.h.shtml#ISDN_MAX_CHANNELS">ISDN_MAX_CHANNELS</A>; i++) {
|
|
<FONT COLOR="#298C52">if</FONT> (ippp_table[i]->state == <A HREF="isdn_ppp.h.shtml#IPPP_OPEN">IPPP_OPEN</A> && !exclusive[ippp_table[i]->minor]) { <FONT COLOR=#0000FF>/* OPEN, but not connected! */</FONT>
|
|
<FONT COLOR="#298C52">break</FONT>;
|
|
}
|
|
}
|
|
} <FONT COLOR="#298C52">else</FONT> {
|
|
<FONT COLOR="#298C52">for</FONT> (i = 0; i < <A HREF="../includes/isdn.h.shtml#ISDN_MAX_CHANNELS">ISDN_MAX_CHANNELS</A>; i++)
|
|
<FONT COLOR="#298C52">if</FONT> (ippp_table[i]->minor == lp->pppbind && ippp_table[i]->state == <A HREF="isdn_ppp.h.shtml#IPPP_OPEN">IPPP_OPEN</A>)
|
|
<FONT COLOR="#298C52">break</FONT>;
|
|
}
|
|
|
|
<FONT COLOR="#298C52">if</FONT> (i >= <A HREF="../includes/isdn.h.shtml#ISDN_MAX_CHANNELS">ISDN_MAX_CHANNELS</A>) {
|
|
<A HREF="kdebug.h.shtml#restore_flags">restore_flags</A>(flags);
|
|
printk(KERN_WARNING <FONT COLOR="#FF0000">"isdn_ppp_bind: Can't find usable ippp device.\n"</FONT>);
|
|
<FONT COLOR="#298C52">return</FONT> -1;
|
|
}
|
|
unit = <A HREF="#isdn_ppp_if_get_unit">isdn_ppp_if_get_unit</A>(lp-><A HREF="isdn_common.c.shtml#name">name</A>); <FONT COLOR=#0000FF>/* get unit number from interface name .. ugly! */</FONT>
|
|
<FONT COLOR="#298C52">if</FONT> (unit < 0) {
|
|
printk(KERN_ERR <FONT COLOR="#FF0000">"isdn_ppp_bind: illegal interface name %s.\n"</FONT>, lp-><A HREF="isdn_common.c.shtml#name">name</A>);
|
|
<FONT COLOR="#298C52">return</FONT> -1;
|
|
}
|
|
lp->ppp_slot = i;
|
|
is = ippp_table[i];
|
|
is->lp = lp;
|
|
is->unit = unit;
|
|
is->state = <A HREF="isdn_ppp.h.shtml#IPPP_OPEN">IPPP_OPEN</A> | <A HREF="isdn_ppp.h.shtml#IPPP_ASSIGNED">IPPP_ASSIGNED</A>; <FONT COLOR=#0000FF>/* assigned to a netdevice but not connected */</FONT>
|
|
|
|
<A HREF="kdebug.h.shtml#restore_flags">restore_flags</A>(flags);
|
|
|
|
<FONT COLOR="#298C52">return</FONT> lp->ppp_slot;
|
|
}
|
|
|
|
<FONT COLOR=#0000FF>/*
|
|
* kick the ipppd on the device
|
|
* (wakes up daemon after B-channel connect)
|
|
*/</FONT>
|
|
|
|
<FONT COLOR="#298C52">void</FONT>
|
|
<A NAME="isdn_ppp_wakeup_daemon">isdn_ppp_wakeup_daemon</A>(isdn_net_local * lp)
|
|
{
|
|
<FONT COLOR="#298C52">if</FONT> (lp->ppp_slot < 0 || lp->ppp_slot >= <A HREF="../includes/isdn.h.shtml#ISDN_MAX_CHANNELS">ISDN_MAX_CHANNELS</A>)
|
|
<FONT COLOR="#298C52">return</FONT>;
|
|
|
|
ippp_table[lp->ppp_slot]->state = <A HREF="isdn_ppp.h.shtml#IPPP_OPEN">IPPP_OPEN</A> | <A HREF="isdn_ppp.h.shtml#IPPP_CONNECT">IPPP_CONNECT</A> | <A HREF="isdn_ppp.h.shtml#IPPP_NOBLOCK">IPPP_NOBLOCK</A>;
|
|
|
|
<FONT COLOR="#298C52">if</FONT> (ippp_table[lp->ppp_slot]->wq)
|
|
wake_up_interruptible(&ippp_table[lp->ppp_slot]->wq);
|
|
}
|
|
|
|
<FONT COLOR=#0000FF>/*
|
|
* there was a hangup on the netdevice
|
|
* force wakeup of the ippp device
|
|
* go into 'device waits for release' state
|
|
*/</FONT>
|
|
<FONT COLOR="#298C52">static</FONT> <FONT COLOR="#298C52">int</FONT>
|
|
<A NAME="isdn_ppp_closewait">isdn_ppp_closewait</A>(<FONT COLOR="#298C52">int</FONT> slot)
|
|
{
|
|
<FONT COLOR="#298C52">struct</FONT> ippp_struct *is;
|
|
|
|
<FONT COLOR="#298C52">if</FONT> (slot < 0 || slot >= <A HREF="../includes/isdn.h.shtml#ISDN_MAX_CHANNELS">ISDN_MAX_CHANNELS</A>)
|
|
<FONT COLOR="#298C52">return</FONT> 0;
|
|
is = ippp_table[slot];
|
|
|
|
<FONT COLOR="#298C52">if</FONT> (is->state && is->wq)
|
|
wake_up_interruptible(&is->wq);
|
|
|
|
is->state = <A HREF="isdn_ppp.h.shtml#IPPP_CLOSEWAIT">IPPP_CLOSEWAIT</A>;
|
|
<FONT COLOR="#298C52">return</FONT> 1;
|
|
}
|
|
|
|
<FONT COLOR=#0000FF>/*
|
|
* isdn_ppp_find_slot / isdn_ppp_free_slot
|
|
*/</FONT>
|
|
|
|
<FONT COLOR="#298C52">static</FONT> <FONT COLOR="#298C52">int</FONT>
|
|
<A NAME="isdn_ppp_get_slot">isdn_ppp_get_slot</A>(<FONT COLOR="#298C52">void</FONT>)
|
|
{
|
|
<FONT COLOR="#298C52">int</FONT> i;
|
|
<FONT COLOR="#298C52">for</FONT> (i = 0; i < <A HREF="../includes/isdn.h.shtml#ISDN_MAX_CHANNELS">ISDN_MAX_CHANNELS</A>; i++) {
|
|
<FONT COLOR="#298C52">if</FONT> (!ippp_table[i]->state)
|
|
<FONT COLOR="#298C52">return</FONT> i;
|
|
}
|
|
<FONT COLOR="#298C52">return</FONT> -1;
|
|
}
|
|
|
|
<FONT COLOR=#0000FF>/*
|
|
* isdn_ppp_open
|
|
*/</FONT>
|
|
|
|
<FONT COLOR="#298C52">int</FONT>
|
|
<A NAME="isdn_ppp_open">isdn_ppp_open</A>(<FONT COLOR="#298C52">int</FONT> min, <FONT COLOR="#298C52">struct</FONT> file *file)
|
|
{
|
|
<FONT COLOR="#298C52">int</FONT> slot;
|
|
<FONT COLOR="#298C52">struct</FONT> ippp_struct *is;
|
|
|
|
<FONT COLOR="#298C52">if</FONT> (min < 0 || min > <A HREF="../includes/isdn.h.shtml#ISDN_MAX_CHANNELS">ISDN_MAX_CHANNELS</A>)
|
|
<FONT COLOR="#298C52">return</FONT> -ENODEV;
|
|
|
|
slot = <A HREF="#isdn_ppp_get_slot">isdn_ppp_get_slot</A>();
|
|
<FONT COLOR="#298C52">if</FONT> (slot < 0) {
|
|
<FONT COLOR="#298C52">return</FONT> -EBUSY;
|
|
}
|
|
is = file->private_data = ippp_table[slot];
|
|
|
|
<FONT COLOR=#A521F7>#if</FONT> 0
|
|
<FONT COLOR="#298C52">if</FONT> (is->debug & 0x1)
|
|
<FONT COLOR=#A521F7>#endif</FONT>
|
|
printk(KERN_DEBUG <FONT COLOR="#FF0000">"ippp, open, slot: %d, minor: %d, state: %04x\n"</FONT>, slot, min, is->state);
|
|
|
|
<FONT COLOR=#0000FF>/* compression stuff */</FONT>
|
|
is->link_compressor = is->compressor = NULL;
|
|
is->link_decompressor = is->decompressor = NULL;
|
|
is->link_comp_stat = is->comp_stat = NULL;
|
|
is->link_decomp_stat = is->decomp_stat = NULL;
|
|
is->compflags = 0;
|
|
|
|
is->lp = NULL;
|
|
is->mp_seqno = 0; <FONT COLOR=#0000FF>/* MP sequence number */</FONT>
|
|
is->pppcfg = 0; <FONT COLOR=#0000FF>/* ppp configuration */</FONT>
|
|
is->mpppcfg = 0; <FONT COLOR=#0000FF>/* mppp configuration */</FONT>
|
|
is->range = 0x1000000; <FONT COLOR=#0000FF>/* MP: 24 bit range */</FONT>
|
|
is->last_link_seqno = -1; <FONT COLOR=#0000FF>/* MP: maybe set to Bundle-MIN, when joining a bundle ?? */</FONT>
|
|
is->unit = -1; <FONT COLOR=#0000FF>/* set, when we have our interface */</FONT>
|
|
is->mru = 1524; <FONT COLOR=#0000FF>/* MRU, default 1524 */</FONT>
|
|
is->maxcid = 16; <FONT COLOR=#0000FF>/* VJ: maxcid */</FONT>
|
|
is->tk = current;
|
|
is->wq = NULL; <FONT COLOR=#0000FF>/* read() wait queue */</FONT>
|
|
is->first = is->rq + <A HREF="../includes/isdn_ppp.h.shtml#NUM_RCV_BUFFS">NUM_RCV_BUFFS</A> - 1; <FONT COLOR=#0000FF>/* receive queue */</FONT>
|
|
is->last = is->rq;
|
|
is->minor = min;
|
|
<FONT COLOR=#A521F7>#ifdef</FONT> CONFIG_ISDN_PPP_VJ
|
|
<FONT COLOR=#0000FF>/*
|
|
* VJ header compression init
|
|
*/</FONT>
|
|
is->slcomp = slhc_init(16, 16); <FONT COLOR=#0000FF>/* not necessary for 2. link in bundle */</FONT>
|
|
<FONT COLOR=#A521F7>#endif</FONT>
|
|
|
|
is->state = <A HREF="isdn_ppp.h.shtml#IPPP_OPEN">IPPP_OPEN</A>;
|
|
|
|
<FONT COLOR="#298C52">return</FONT> 0;
|
|
}
|
|
|
|
<FONT COLOR=#0000FF>/*
|
|
* release ippp device
|
|
*/</FONT>
|
|
<FONT COLOR="#298C52">void</FONT>
|
|
<A NAME="isdn_ppp_release">isdn_ppp_release</A>(<FONT COLOR="#298C52">int</FONT> min, <FONT COLOR="#298C52">struct</FONT> file *file)
|
|
{
|
|
<FONT COLOR="#298C52">int</FONT> i;
|
|
<FONT COLOR="#298C52">struct</FONT> ippp_struct *is;
|
|
|
|
<FONT COLOR="#298C52">if</FONT> (min < 0 || min >= <A HREF="../includes/isdn.h.shtml#ISDN_MAX_CHANNELS">ISDN_MAX_CHANNELS</A>)
|
|
<FONT COLOR="#298C52">return</FONT>;
|
|
is = file->private_data;
|
|
|
|
<FONT COLOR="#298C52">if</FONT> (is->debug & 0x1)
|
|
printk(KERN_DEBUG <FONT COLOR="#FF0000">"ippp: release, minor: %d %lx\n"</FONT>, min, (<FONT COLOR="#298C52">long</FONT>) is->lp);
|
|
|
|
<FONT COLOR="#298C52">if</FONT> (is->lp) { <FONT COLOR=#0000FF>/* a lp address says: this link is still up */</FONT>
|
|
<A HREF="../includes/isdn.h.shtml#isdn_net_dev">isdn_net_dev</A> *p = is->lp->netdev;
|
|
|
|
is->state &= ~<A HREF="isdn_ppp.h.shtml#IPPP_CONNECT">IPPP_CONNECT</A>; <FONT COLOR=#0000FF>/* -> effect: no call of wakeup */</FONT>
|
|
<FONT COLOR=#0000FF>/*
|
|
* isdn_net_hangup() calls isdn_ppp_free()
|
|
* isdn_ppp_free() sets is->lp to NULL and lp->ppp_slot to -1
|
|
* removing the IPPP_CONNECT flag omits calling of isdn_ppp_wakeup_daemon()
|
|
*/</FONT>
|
|
<A HREF="isdn_net.c.shtml#isdn_net_hangup">isdn_net_hangup</A>(&p->dev);
|
|
}
|
|
<FONT COLOR="#298C52">for</FONT> (i = 0; i < <A HREF="../includes/isdn_ppp.h.shtml#NUM_RCV_BUFFS">NUM_RCV_BUFFS</A>; i++) {
|
|
<FONT COLOR="#298C52">if</FONT> (is->rq[i].buf) {
|
|
kfree(is->rq[i].buf);
|
|
is->rq[i].buf = NULL;
|
|
}
|
|
}
|
|
is->first = is->rq + <A HREF="../includes/isdn_ppp.h.shtml#NUM_RCV_BUFFS">NUM_RCV_BUFFS</A> - 1; <FONT COLOR=#0000FF>/* receive queue */</FONT>
|
|
is->last = is->rq;
|
|
|
|
<FONT COLOR=#A521F7>#ifdef</FONT> CONFIG_ISDN_PPP_VJ
|
|
<FONT COLOR=#0000FF>/* TODO: if this was the previous master: link the slcomp to the new master */</FONT>
|
|
slhc_free(is->slcomp);
|
|
is->slcomp = NULL;
|
|
<FONT COLOR=#A521F7>#endif</FONT>
|
|
|
|
<FONT COLOR=#0000FF>/* TODO: if this was the previous master: link the the stuff to the new master */</FONT>
|
|
<FONT COLOR="#298C52">if</FONT>(is->comp_stat)
|
|
is->compressor->free(is->comp_stat);
|
|
<FONT COLOR="#298C52">if</FONT>(is->link_comp_stat)
|
|
is->link_compressor->free(is->link_comp_stat);
|
|
<FONT COLOR="#298C52">if</FONT>(is->link_decomp_stat)
|
|
is->link_decompressor->free(is->link_decomp_stat);
|
|
<FONT COLOR="#298C52">if</FONT>(is->decomp_stat)
|
|
is->decompressor->free(is->decomp_stat);
|
|
is->compressor = is->link_compressor = NULL;
|
|
is->decompressor = is->link_decompressor = NULL;
|
|
is->comp_stat = is->link_comp_stat = NULL;
|
|
is->decomp_stat = is->link_decomp_stat = NULL;
|
|
|
|
<FONT COLOR=#0000FF>/* this slot is ready for new connections */</FONT>
|
|
is->state = 0;
|
|
}
|
|
|
|
<FONT COLOR=#0000FF>/*
|
|
* get_arg .. ioctl helper
|
|
*/</FONT>
|
|
<FONT COLOR="#298C52">static</FONT> <FONT COLOR="#298C52">int</FONT>
|
|
<A NAME="get_arg">get_arg</A>(<FONT COLOR="#298C52">void</FONT> *b, <FONT COLOR="#298C52">void</FONT> *val, <FONT COLOR="#298C52">int</FONT> len)
|
|
{
|
|
<FONT COLOR="#298C52">if</FONT> (len <= 0)
|
|
len = <FONT COLOR="#298C52">sizeof</FONT>(<FONT COLOR="#298C52">void</FONT> *);
|
|
<FONT COLOR="#298C52">if</FONT> (copy_from_user((<FONT COLOR="#298C52">void</FONT> *) val, b, len))
|
|
<FONT COLOR="#298C52">return</FONT> -EFAULT;
|
|
<FONT COLOR="#298C52">return</FONT> 0;
|
|
}
|
|
|
|
<FONT COLOR=#0000FF>/*
|
|
* set arg .. ioctl helper
|
|
*/</FONT>
|
|
<FONT COLOR="#298C52">static</FONT> <FONT COLOR="#298C52">int</FONT>
|
|
<A NAME="set_arg">set_arg</A>(<FONT COLOR="#298C52">void</FONT> *b, <FONT COLOR="#298C52">void</FONT> *val,<FONT COLOR="#298C52">int</FONT> len)
|
|
{
|
|
<FONT COLOR="#298C52">if</FONT>(len <= 0)
|
|
len = <FONT COLOR="#298C52">sizeof</FONT>(<FONT COLOR="#298C52">void</FONT> *);
|
|
<FONT COLOR="#298C52">if</FONT> (copy_to_user(b, (<FONT COLOR="#298C52">void</FONT> *) val, len))
|
|
<FONT COLOR="#298C52">return</FONT> -EFAULT;
|
|
<FONT COLOR="#298C52">return</FONT> 0;
|
|
}
|
|
|
|
<FONT COLOR=#0000FF>/*
|
|
* ippp device ioctl
|
|
*/</FONT>
|
|
<FONT COLOR="#298C52">int</FONT>
|
|
<A HREF="#isdn_ppp_ioctl">isdn_ppp_ioctl</A>(<FONT COLOR="#298C52">int</FONT> min, <FONT COLOR="#298C52">struct</FONT> file *file, <FONT COLOR="#298C52">unsigned</FONT> <FONT COLOR="#298C52">int</FONT> cmd, <FONT COLOR="#298C52">unsigned</FONT> <FONT COLOR="#298C52">long</FONT> arg)
|
|
{
|
|
<FONT COLOR="#298C52">unsigned</FONT> <FONT COLOR="#298C52">long</FONT> val;
|
|
<FONT COLOR="#298C52">int</FONT> r,i,j;
|
|
<FONT COLOR="#298C52">struct</FONT> ippp_struct *is;
|
|
isdn_net_local *lp;
|
|
<FONT COLOR="#298C52">struct</FONT> isdn_ppp_comp_data data;
|
|
|
|
is = (<FONT COLOR="#298C52">struct</FONT> ippp_struct *) file->private_data;
|
|
lp = is->lp;
|
|
|
|
<FONT COLOR="#298C52">if</FONT> (is->debug & 0x1)
|
|
printk(KERN_DEBUG <FONT COLOR="#FF0000">"isdn_ppp_ioctl: minor: %d cmd: %x state: %x\n"</FONT>, min, cmd, is->state);
|
|
|
|
<FONT COLOR="#298C52">if</FONT> (!(is->state & <A HREF="isdn_ppp.h.shtml#IPPP_OPEN">IPPP_OPEN</A>))
|
|
<FONT COLOR="#298C52">return</FONT> -EINVAL;
|
|
|
|
<FONT COLOR="#298C52">switch</FONT> (cmd) {
|
|
<FONT COLOR="#298C52">case</FONT> <A HREF="../includes/isdn_ppp.h.shtml#PPPIOCBUNDLE">PPPIOCBUNDLE</A>:
|
|
<FONT COLOR=#A521F7>#ifdef</FONT> CONFIG_ISDN_MPP
|
|
<FONT COLOR="#298C52">if</FONT> (!(is->state & <A HREF="isdn_ppp.h.shtml#IPPP_CONNECT">IPPP_CONNECT</A>))
|
|
<FONT COLOR="#298C52">return</FONT> -EINVAL;
|
|
<FONT COLOR="#298C52">if</FONT> ((r = <A HREF="#get_arg">get_arg</A>((<FONT COLOR="#298C52">void</FONT> *) arg, &val, <FONT COLOR="#298C52">sizeof</FONT>(val) )))
|
|
<FONT COLOR="#298C52">return</FONT> r;
|
|
printk(KERN_DEBUG <FONT COLOR="#FF0000">"iPPP-bundle: minor: %d, slave unit: %d, master unit: %d\n"</FONT>,
|
|
(<FONT COLOR="#298C52">int</FONT>) min, (<FONT COLOR="#298C52">int</FONT>) is->unit, (<FONT COLOR="#298C52">int</FONT>) val);
|
|
<FONT COLOR="#298C52">return</FONT> <A HREF="#isdn_ppp_bundle">isdn_ppp_bundle</A>(is, val);
|
|
<FONT COLOR=#A521F7>#else</FONT>
|
|
<FONT COLOR="#298C52">return</FONT> -1;
|
|
<FONT COLOR=#A521F7>#endif</FONT>
|
|
<FONT COLOR="#298C52">break</FONT>;
|
|
<FONT COLOR="#298C52">case</FONT> PPPIOCGUNIT: <FONT COLOR=#0000FF>/* get ppp/isdn unit number */</FONT>
|
|
<FONT COLOR="#298C52">if</FONT> ((r = <A HREF="#set_arg">set_arg</A>((<FONT COLOR="#298C52">void</FONT> *) arg, &is->unit, <FONT COLOR="#298C52">sizeof</FONT>(is->unit) )))
|
|
<FONT COLOR="#298C52">return</FONT> r;
|
|
<FONT COLOR="#298C52">break</FONT>;
|
|
<FONT COLOR="#298C52">case</FONT> <A HREF="../includes/isdn_ppp.h.shtml#PPPIOCGIFNAME">PPPIOCGIFNAME</A>:
|
|
<FONT COLOR="#298C52">if</FONT>(!lp)
|
|
<FONT COLOR="#298C52">return</FONT> -EINVAL;
|
|
<FONT COLOR="#298C52">if</FONT> ((r = <A HREF="#set_arg">set_arg</A>((<FONT COLOR="#298C52">void</FONT> *) arg, lp-><A HREF="isdn_common.c.shtml#name">name</A>,strlen(lp-><A HREF="isdn_common.c.shtml#name">name</A>))))
|
|
<FONT COLOR="#298C52">return</FONT> r;
|
|
<FONT COLOR="#298C52">break</FONT>;
|
|
<FONT COLOR="#298C52">case</FONT> <A HREF="../includes/isdn_ppp.h.shtml#PPPIOCGMPFLAGS">PPPIOCGMPFLAGS</A>: <FONT COLOR=#0000FF>/* get configuration flags */</FONT>
|
|
<FONT COLOR="#298C52">if</FONT> ((r = <A HREF="#set_arg">set_arg</A>((<FONT COLOR="#298C52">void</FONT> *) arg, &is->mpppcfg, <FONT COLOR="#298C52">sizeof</FONT>(is->mpppcfg) )))
|
|
<FONT COLOR="#298C52">return</FONT> r;
|
|
<FONT COLOR="#298C52">break</FONT>;
|
|
<FONT COLOR="#298C52">case</FONT> <A HREF="../includes/isdn_ppp.h.shtml#PPPIOCSMPFLAGS">PPPIOCSMPFLAGS</A>: <FONT COLOR=#0000FF>/* set configuration flags */</FONT>
|
|
<FONT COLOR="#298C52">if</FONT> ((r = <A HREF="#get_arg">get_arg</A>((<FONT COLOR="#298C52">void</FONT> *) arg, &val, <FONT COLOR="#298C52">sizeof</FONT>(val) )))
|
|
<FONT COLOR="#298C52">return</FONT> r;
|
|
is->mpppcfg = val;
|
|
<FONT COLOR="#298C52">break</FONT>;
|
|
<FONT COLOR="#298C52">case</FONT> PPPIOCGFLAGS: <FONT COLOR=#0000FF>/* get configuration flags */</FONT>
|
|
<FONT COLOR="#298C52">if</FONT> ((r = <A HREF="#set_arg">set_arg</A>((<FONT COLOR="#298C52">void</FONT> *) arg, &is->pppcfg,<FONT COLOR="#298C52">sizeof</FONT>(is->pppcfg) )))
|
|
<FONT COLOR="#298C52">return</FONT> r;
|
|
<FONT COLOR="#298C52">break</FONT>;
|
|
<FONT COLOR="#298C52">case</FONT> PPPIOCSFLAGS: <FONT COLOR=#0000FF>/* set configuration flags */</FONT>
|
|
<FONT COLOR="#298C52">if</FONT> ((r = <A HREF="#get_arg">get_arg</A>((<FONT COLOR="#298C52">void</FONT> *) arg, &val, <FONT COLOR="#298C52">sizeof</FONT>(val) ))) {
|
|
<FONT COLOR="#298C52">return</FONT> r;
|
|
}
|
|
<FONT COLOR="#298C52">if</FONT> (val & SC_ENABLE_IP && !(is->pppcfg & SC_ENABLE_IP) && (is->state & <A HREF="isdn_ppp.h.shtml#IPPP_CONNECT">IPPP_CONNECT</A>)) {
|
|
<FONT COLOR="#298C52">if</FONT> (lp) {
|
|
lp->netdev->dev.tbusy = 0;
|
|
mark_bh(NET_BH); <FONT COLOR=#0000FF>/* OK .. we are ready to send buffers */</FONT>
|
|
}
|
|
}
|
|
is->pppcfg = val;
|
|
<FONT COLOR="#298C52">break</FONT>;
|
|
<FONT COLOR=#A521F7>#if</FONT> 0
|
|
<FONT COLOR="#298C52">case</FONT> PPPIOCGSTAT: <FONT COLOR=#0000FF>/* read PPP statistic information */</FONT>
|
|
<FONT COLOR="#298C52">break</FONT>;
|
|
<FONT COLOR=#A521F7>#endif</FONT>
|
|
<FONT COLOR="#298C52">case</FONT> PPPIOCGIDLE: <FONT COLOR=#0000FF>/* get idle time information */</FONT>
|
|
<FONT COLOR="#298C52">if</FONT> (lp) {
|
|
<FONT COLOR="#298C52">struct</FONT> ppp_idle pidle;
|
|
pidle.xmit_idle = pidle.recv_idle = lp->huptimer;
|
|
<FONT COLOR="#298C52">if</FONT> ((r = <A HREF="#set_arg">set_arg</A>((<FONT COLOR="#298C52">void</FONT> *) arg, &pidle,<FONT COLOR="#298C52">sizeof</FONT>(<FONT COLOR="#298C52">struct</FONT> ppp_idle))))
|
|
<FONT COLOR="#298C52">return</FONT> r;
|
|
}
|
|
<FONT COLOR="#298C52">break</FONT>;
|
|
<FONT COLOR="#298C52">case</FONT> PPPIOCSMRU: <FONT COLOR=#0000FF>/* set receive unit size for PPP */</FONT>
|
|
<FONT COLOR="#298C52">if</FONT> ((r = <A HREF="#get_arg">get_arg</A>((<FONT COLOR="#298C52">void</FONT> *) arg, &val, <FONT COLOR="#298C52">sizeof</FONT>(val) )))
|
|
<FONT COLOR="#298C52">return</FONT> r;
|
|
is->mru = val;
|
|
<FONT COLOR="#298C52">break</FONT>;
|
|
<FONT COLOR="#298C52">case</FONT> <A HREF="../includes/isdn_ppp.h.shtml#PPPIOCSMPMRU">PPPIOCSMPMRU</A>:
|
|
<FONT COLOR="#298C52">break</FONT>;
|
|
<FONT COLOR="#298C52">case</FONT> <A HREF="../includes/isdn_ppp.h.shtml#PPPIOCSMPMTU">PPPIOCSMPMTU</A>:
|
|
<FONT COLOR="#298C52">break</FONT>;
|
|
<FONT COLOR="#298C52">case</FONT> PPPIOCSMAXCID: <FONT COLOR=#0000FF>/* set the maximum compression slot id */</FONT>
|
|
<FONT COLOR="#298C52">if</FONT> ((r = <A HREF="#get_arg">get_arg</A>((<FONT COLOR="#298C52">void</FONT> *) arg, &val, <FONT COLOR="#298C52">sizeof</FONT>(val) )))
|
|
<FONT COLOR="#298C52">return</FONT> r;
|
|
val++;
|
|
<FONT COLOR="#298C52">if</FONT> (is->maxcid != val) {
|
|
<FONT COLOR=#A521F7>#ifdef</FONT> CONFIG_ISDN_PPP_VJ
|
|
<FONT COLOR="#298C52">struct</FONT> slcompress *sltmp;
|
|
<FONT COLOR=#A521F7>#endif</FONT>
|
|
<FONT COLOR="#298C52">if</FONT> (is->debug & 0x1)
|
|
printk(KERN_DEBUG <FONT COLOR="#FF0000">"ippp, ioctl: changed MAXCID to %ld\n"</FONT>, val);
|
|
is->maxcid = val;
|
|
<FONT COLOR=#A521F7>#ifdef</FONT> CONFIG_ISDN_PPP_VJ
|
|
sltmp = slhc_init(16, val);
|
|
<FONT COLOR="#298C52">if</FONT> (!sltmp) {
|
|
printk(KERN_ERR <FONT COLOR="#FF0000">"ippp, can't realloc slhc struct\n"</FONT>);
|
|
<FONT COLOR="#298C52">return</FONT> -ENOMEM;
|
|
}
|
|
<FONT COLOR="#298C52">if</FONT> (is->slcomp)
|
|
slhc_free(is->slcomp);
|
|
is->slcomp = sltmp;
|
|
<FONT COLOR=#A521F7>#endif</FONT>
|
|
}
|
|
<FONT COLOR="#298C52">break</FONT>;
|
|
<FONT COLOR="#298C52">case</FONT> PPPIOCGDEBUG:
|
|
<FONT COLOR="#298C52">if</FONT> ((r = <A HREF="#set_arg">set_arg</A>((<FONT COLOR="#298C52">void</FONT> *) arg, &is->debug, <FONT COLOR="#298C52">sizeof</FONT>(is->debug) )))
|
|
<FONT COLOR="#298C52">return</FONT> r;
|
|
<FONT COLOR="#298C52">break</FONT>;
|
|
<FONT COLOR="#298C52">case</FONT> PPPIOCSDEBUG:
|
|
<FONT COLOR="#298C52">if</FONT> ((r = <A HREF="#get_arg">get_arg</A>((<FONT COLOR="#298C52">void</FONT> *) arg, &val, <FONT COLOR="#298C52">sizeof</FONT>(val) )))
|
|
<FONT COLOR="#298C52">return</FONT> r;
|
|
is->debug = val;
|
|
<FONT COLOR="#298C52">break</FONT>;
|
|
<FONT COLOR="#298C52">case</FONT> <A HREF="../includes/isdn_ppp.h.shtml#PPPIOCGCOMPRESSORS">PPPIOCGCOMPRESSORS</A>:
|
|
{
|
|
<FONT COLOR="#298C52">unsigned</FONT> <FONT COLOR="#298C52">long</FONT> protos[8] = {0,};
|
|
<FONT COLOR="#298C52">struct</FONT> isdn_ppp_compressor *ipc = ipc_head;
|
|
<FONT COLOR="#298C52">while</FONT>(ipc) {
|
|
j = ipc->num / (<FONT COLOR="#298C52">sizeof</FONT>(<FONT COLOR="#298C52">long</FONT>)*8);
|
|
i = ipc->num % (<FONT COLOR="#298C52">sizeof</FONT>(<FONT COLOR="#298C52">long</FONT>)*8);
|
|
<FONT COLOR="#298C52">if</FONT>(j < 8)
|
|
protos[j] |= (0x1<<i);
|
|
ipc = ipc->next;
|
|
}
|
|
<FONT COLOR="#298C52">if</FONT> ((r = <A HREF="#set_arg">set_arg</A>((<FONT COLOR="#298C52">void</FONT> *) arg,protos,8*<FONT COLOR="#298C52">sizeof</FONT>(<FONT COLOR="#298C52">long</FONT>) )))
|
|
<FONT COLOR="#298C52">return</FONT> r;
|
|
}
|
|
<FONT COLOR="#298C52">break</FONT>;
|
|
<FONT COLOR="#298C52">case</FONT> <A HREF="../includes/isdn_ppp.h.shtml#PPPIOCSCOMPRESSOR">PPPIOCSCOMPRESSOR</A>:
|
|
<FONT COLOR="#298C52">if</FONT> ((r = <A HREF="#get_arg">get_arg</A>((<FONT COLOR="#298C52">void</FONT> *) arg, &data, <FONT COLOR="#298C52">sizeof</FONT>(<FONT COLOR="#298C52">struct</FONT> isdn_ppp_comp_data))))
|
|
<FONT COLOR="#298C52">return</FONT> r;
|
|
<FONT COLOR="#298C52">return</FONT> <A HREF="#isdn_ppp_set_compressor">isdn_ppp_set_compressor</A>(is, &data);
|
|
<FONT COLOR="#298C52">case</FONT> <A HREF="../includes/isdn_ppp.h.shtml#PPPIOCGCALLINFO">PPPIOCGCALLINFO</A>:
|
|
{
|
|
<FONT COLOR="#298C52">struct</FONT> pppcallinfo pci;
|
|
memset((<FONT COLOR="#298C52">char</FONT> *) &pci,0,<FONT COLOR="#298C52">sizeof</FONT>(<FONT COLOR="#298C52">struct</FONT> pppcallinfo));
|
|
<FONT COLOR="#298C52">if</FONT>(lp)
|
|
{
|
|
strncpy(pci.local_num,lp->msn,63);
|
|
<FONT COLOR="#298C52">if</FONT>(lp->dial) {
|
|
strncpy(pci.remote_num,lp->dial->num,63);
|
|
}
|
|
pci.charge_units = lp->charge;
|
|
<FONT COLOR="#298C52">if</FONT>(lp->outgoing)
|
|
pci.calltype = <A HREF="../includes/isdn_ppp.h.shtml#CALLTYPE_OUTGOING">CALLTYPE_OUTGOING</A>;
|
|
<FONT COLOR="#298C52">else</FONT>
|
|
pci.calltype = <A HREF="../includes/isdn_ppp.h.shtml#CALLTYPE_INCOMING">CALLTYPE_INCOMING</A>;
|
|
<FONT COLOR="#298C52">if</FONT>(lp->flags & <A HREF="../includes/isdn.h.shtml#ISDN_NET_CALLBACK">ISDN_NET_CALLBACK</A>)
|
|
pci.calltype |= <A HREF="../includes/isdn_ppp.h.shtml#CALLTYPE_CALLBACK">CALLTYPE_CALLBACK</A>;
|
|
}
|
|
<FONT COLOR="#298C52">return</FONT> <A HREF="#set_arg">set_arg</A>((<FONT COLOR="#298C52">void</FONT> *)arg,&pci,<FONT COLOR="#298C52">sizeof</FONT>(<FONT COLOR="#298C52">struct</FONT> pppcallinfo));
|
|
}
|
|
<FONT COLOR="#298C52">default</FONT>:
|
|
<FONT COLOR="#298C52">break</FONT>;
|
|
}
|
|
<FONT COLOR="#298C52">return</FONT> 0;
|
|
}
|
|
|
|
<FONT COLOR="#298C52">unsigned</FONT> <FONT COLOR="#298C52">int</FONT>
|
|
<A HREF="#isdn_ppp_poll">isdn_ppp_poll</A>(<FONT COLOR="#298C52">struct</FONT> file *file, poll_table * wait)
|
|
{
|
|
<FONT COLOR="#298C52">unsigned</FONT> <FONT COLOR="#298C52">int</FONT> mask;
|
|
<FONT COLOR="#298C52">struct</FONT> ippp_buf_queue *bf;
|
|
<FONT COLOR="#298C52">struct</FONT> ippp_buf_queue *bl;
|
|
<FONT COLOR="#298C52">unsigned</FONT> <FONT COLOR="#298C52">long</FONT> flags;
|
|
<FONT COLOR="#298C52">struct</FONT> ippp_struct *is;
|
|
|
|
is = file->private_data;
|
|
|
|
<FONT COLOR="#298C52">if</FONT> (is->debug & 0x2)
|
|
printk(KERN_DEBUG <FONT COLOR="#FF0000">"isdn_ppp_poll: minor: %d\n"</FONT>,
|
|
MINOR(file->f_dentry->d_inode->i_rdev));
|
|
|
|
<FONT COLOR=#0000FF>/* just registers wait_queue hook. This doesn't really wait. */</FONT>
|
|
<A HREF="../includes/isdn.h.shtml#poll_wait">poll_wait</A>(file, &is->wq, wait);
|
|
|
|
<FONT COLOR="#298C52">if</FONT> (!(is->state & <A HREF="isdn_ppp.h.shtml#IPPP_OPEN">IPPP_OPEN</A>)) {
|
|
<FONT COLOR="#298C52">if</FONT>(is->state == <A HREF="isdn_ppp.h.shtml#IPPP_CLOSEWAIT">IPPP_CLOSEWAIT</A>)
|
|
<FONT COLOR="#298C52">return</FONT> POLLHUP;
|
|
printk(KERN_DEBUG <FONT COLOR="#FF0000">"isdn_ppp: device not open\n"</FONT>);
|
|
<FONT COLOR="#298C52">return</FONT> POLLERR;
|
|
}
|
|
<FONT COLOR=#0000FF>/* we're always ready to send .. */</FONT>
|
|
mask = POLLOUT | POLLWRNORM;
|
|
|
|
save_flags(flags);
|
|
<A HREF="kdebug.h.shtml#cli">cli</A>();
|
|
bl = is->last;
|
|
bf = is->first;
|
|
<FONT COLOR=#0000FF>/*
|
|
* if IPPP_NOBLOCK is set we return even if we have nothing to read
|
|
*/</FONT>
|
|
<FONT COLOR="#298C52">if</FONT> (bf->next != bl || (is->state & <A HREF="isdn_ppp.h.shtml#IPPP_NOBLOCK">IPPP_NOBLOCK</A>)) {
|
|
is->state &= ~<A HREF="isdn_ppp.h.shtml#IPPP_NOBLOCK">IPPP_NOBLOCK</A>;
|
|
mask |= POLLIN | POLLRDNORM;
|
|
}
|
|
<A HREF="kdebug.h.shtml#restore_flags">restore_flags</A>(flags);
|
|
<FONT COLOR="#298C52">return</FONT> mask;
|
|
}
|
|
|
|
<FONT COLOR=#0000FF>/*
|
|
* fill up isdn_ppp_read() queue ..
|
|
*/</FONT>
|
|
|
|
<FONT COLOR="#298C52">static</FONT> <FONT COLOR="#298C52">int</FONT>
|
|
<A HREF="#isdn_ppp_fill_rq">isdn_ppp_fill_rq</A>(<FONT COLOR="#298C52">unsigned</FONT> <FONT COLOR="#298C52">char</FONT> *buf, <FONT COLOR="#298C52">int</FONT> len, <FONT COLOR="#298C52">int</FONT> proto, <FONT COLOR="#298C52">int</FONT> slot)
|
|
{
|
|
<FONT COLOR="#298C52">struct</FONT> ippp_buf_queue *bf,
|
|
*bl;
|
|
<FONT COLOR="#298C52">unsigned</FONT> <FONT COLOR="#298C52">long</FONT> flags;
|
|
<FONT COLOR="#298C52">unsigned</FONT> <FONT COLOR="#298C52">char</FONT> *nbuf;
|
|
<FONT COLOR="#298C52">struct</FONT> ippp_struct *is;
|
|
|
|
<FONT COLOR="#298C52">if</FONT> (slot < 0 || slot >= <A HREF="../includes/isdn.h.shtml#ISDN_MAX_CHANNELS">ISDN_MAX_CHANNELS</A>) {
|
|
printk(KERN_WARNING <FONT COLOR="#FF0000">"ippp: illegal slot.\n"</FONT>);
|
|
<FONT COLOR="#298C52">return</FONT> 0;
|
|
}
|
|
is = ippp_table[slot];
|
|
|
|
<FONT COLOR="#298C52">if</FONT> (!(is->state & <A HREF="isdn_ppp.h.shtml#IPPP_CONNECT">IPPP_CONNECT</A>)) {
|
|
printk(KERN_DEBUG <FONT COLOR="#FF0000">"ippp: device not activated.\n"</FONT>);
|
|
<FONT COLOR="#298C52">return</FONT> 0;
|
|
}
|
|
nbuf = (<FONT COLOR="#298C52">unsigned</FONT> <FONT COLOR="#298C52">char</FONT> *) kmalloc(len + 4, GFP_ATOMIC);
|
|
<FONT COLOR="#298C52">if</FONT> (!nbuf) {
|
|
printk(KERN_WARNING <FONT COLOR="#FF0000">"ippp: Can't alloc buf\n"</FONT>);
|
|
<FONT COLOR="#298C52">return</FONT> 0;
|
|
}
|
|
nbuf[0] = PPP_ALLSTATIONS;
|
|
nbuf[1] = PPP_UI;
|
|
nbuf[2] = proto >> 8;
|
|
nbuf[3] = proto & 0xff;
|
|
memcpy(nbuf + 4, buf, len);
|
|
|
|
save_flags(flags);
|
|
<A HREF="kdebug.h.shtml#cli">cli</A>();
|
|
|
|
bf = is->first;
|
|
bl = is->last;
|
|
|
|
<FONT COLOR="#298C52">if</FONT> (bf == bl) {
|
|
printk(KERN_WARNING <FONT COLOR="#FF0000">"ippp: Queue is full; discarding first buffer\n"</FONT>);
|
|
bf = bf->next;
|
|
kfree(bf->buf);
|
|
is->first = bf;
|
|
}
|
|
bl->buf = (<FONT COLOR="#298C52">char</FONT> *) nbuf;
|
|
bl->len = len + 4;
|
|
|
|
is->last = bl->next;
|
|
<A HREF="kdebug.h.shtml#restore_flags">restore_flags</A>(flags);
|
|
|
|
<FONT COLOR="#298C52">if</FONT> (is->wq)
|
|
wake_up_interruptible(&is->wq);
|
|
|
|
<FONT COLOR="#298C52">return</FONT> len;
|
|
}
|
|
|
|
<FONT COLOR=#0000FF>/*
|
|
* read() .. non-blocking: ipppd calls it only after select()
|
|
* reports, that there is data
|
|
*/</FONT>
|
|
|
|
<FONT COLOR="#298C52">int</FONT>
|
|
<A HREF="#isdn_ppp_read">isdn_ppp_read</A>(<FONT COLOR="#298C52">int</FONT> min, <FONT COLOR="#298C52">struct</FONT> file *file, <FONT COLOR="#298C52">char</FONT> *buf, <FONT COLOR="#298C52">int</FONT> count)
|
|
{
|
|
<FONT COLOR="#298C52">struct</FONT> ippp_struct *is;
|
|
<FONT COLOR="#298C52">struct</FONT> ippp_buf_queue *b;
|
|
<FONT COLOR="#298C52">int</FONT> r;
|
|
<FONT COLOR="#298C52">unsigned</FONT> <FONT COLOR="#298C52">long</FONT> flags;
|
|
<FONT COLOR="#298C52">unsigned</FONT> <FONT COLOR="#298C52">char</FONT> *save_buf;
|
|
|
|
is = file->private_data;
|
|
|
|
<FONT COLOR="#298C52">if</FONT> (!(is->state & <A HREF="isdn_ppp.h.shtml#IPPP_OPEN">IPPP_OPEN</A>))
|
|
<FONT COLOR="#298C52">return</FONT> 0;
|
|
|
|
<FONT COLOR="#298C52">if</FONT> ((r = verify_area(VERIFY_WRITE, (<FONT COLOR="#298C52">void</FONT> *) buf, count)))
|
|
<FONT COLOR="#298C52">return</FONT> r;
|
|
|
|
save_flags(flags);
|
|
<A HREF="kdebug.h.shtml#cli">cli</A>();
|
|
|
|
b = is->first->next;
|
|
save_buf = b->buf;
|
|
<FONT COLOR="#298C52">if</FONT> (!save_buf) {
|
|
<A HREF="kdebug.h.shtml#restore_flags">restore_flags</A>(flags);
|
|
<FONT COLOR="#298C52">return</FONT> -EAGAIN;
|
|
}
|
|
<FONT COLOR="#298C52">if</FONT> (b->len < count)
|
|
count = b->len;
|
|
b->buf = NULL;
|
|
is->first = b;
|
|
|
|
<A HREF="kdebug.h.shtml#restore_flags">restore_flags</A>(flags);
|
|
|
|
copy_to_user(buf, save_buf, count);
|
|
kfree(save_buf);
|
|
|
|
<FONT COLOR="#298C52">return</FONT> count;
|
|
}
|
|
|
|
<FONT COLOR=#0000FF>/*
|
|
* ipppd wanna write a packet to the card .. non-blocking
|
|
*/</FONT>
|
|
|
|
<FONT COLOR="#298C52">int</FONT>
|
|
<A HREF="#isdn_ppp_write">isdn_ppp_write</A>(<FONT COLOR="#298C52">int</FONT> min, <FONT COLOR="#298C52">struct</FONT> file *file, <FONT COLOR="#298C52">const</FONT> <FONT COLOR="#298C52">char</FONT> *buf, <FONT COLOR="#298C52">int</FONT> count)
|
|
{
|
|
isdn_net_local *lp;
|
|
<FONT COLOR="#298C52">struct</FONT> ippp_struct *is;
|
|
<FONT COLOR=#A521F7>#ifndef</FONT> CONFIG_ISDN_TIMEOUT_RULES
|
|
<FONT COLOR="#298C52">int</FONT> proto;
|
|
<FONT COLOR="#298C52">unsigned</FONT> <FONT COLOR="#298C52">char</FONT> protobuf[4];
|
|
<FONT COLOR=#A521F7>#endif</FONT>
|
|
|
|
is = file->private_data;
|
|
|
|
<FONT COLOR="#298C52">if</FONT> (!(is->state & <A HREF="isdn_ppp.h.shtml#IPPP_CONNECT">IPPP_CONNECT</A>))
|
|
<FONT COLOR="#298C52">return</FONT> 0;
|
|
|
|
lp = is->lp;
|
|
|
|
<FONT COLOR=#0000FF>/* -> push it directly to the lowlevel interface */</FONT>
|
|
|
|
<FONT COLOR="#298C52">if</FONT> (!lp)
|
|
printk(KERN_DEBUG <FONT COLOR="#FF0000">"isdn_ppp_write: lp == NULL\n"</FONT>);
|
|
<FONT COLOR="#298C52">else</FONT> {
|
|
<FONT COLOR=#A521F7>#ifndef</FONT> CONFIG_ISDN_TIMEOUT_RULES
|
|
<FONT COLOR=#0000FF>/*
|
|
* Don't reset huptimer for
|
|
* LCP packets. (Echo requests).
|
|
*/</FONT>
|
|
<FONT COLOR="#298C52">if</FONT> (copy_from_user(protobuf, buf, 4))
|
|
<FONT COLOR="#298C52">return</FONT> -EFAULT;
|
|
proto = PPP_PROTOCOL(protobuf);
|
|
<FONT COLOR="#298C52">if</FONT> (proto != PPP_LCP)
|
|
lp->huptimer = 0;
|
|
<FONT COLOR=#A521F7>#endif</FONT>
|
|
|
|
<FONT COLOR="#298C52">if</FONT> (lp->isdn_device < 0 || lp->isdn_channel < 0)
|
|
<FONT COLOR="#298C52">return</FONT> 0;
|
|
|
|
<FONT COLOR="#298C52">if</FONT> (dev->drv[lp->isdn_device]->running && lp->dialstate == 0 &&
|
|
(lp->flags & <A HREF="../includes/isdn.h.shtml#ISDN_NET_CONNECTED">ISDN_NET_CONNECTED</A>)) {
|
|
<FONT COLOR="#298C52">int</FONT> cnt;
|
|
<FONT COLOR="#298C52">struct</FONT> sk_buff *skb;
|
|
skb = dev_alloc_skb(count);
|
|
<FONT COLOR="#298C52">if</FONT> (!skb) {
|
|
printk(KERN_WARNING <FONT COLOR="#FF0000">"isdn_ppp_write: out of memory!\n"</FONT>);
|
|
<FONT COLOR="#298C52">return</FONT> count;
|
|
}
|
|
<FONT COLOR="#298C52">if</FONT> (copy_from_user(skb_put(skb, count), buf, count))
|
|
<FONT COLOR="#298C52">return</FONT> -EFAULT;
|
|
<FONT COLOR="#298C52">if</FONT> (is->debug & 0x40) {
|
|
printk(KERN_DEBUG <FONT COLOR="#FF0000">"ppp xmit: len %d\n"</FONT>, (<FONT COLOR="#298C52">int</FONT>) skb->len);
|
|
<A HREF="#isdn_ppp_frame_log">isdn_ppp_frame_log</A>(<FONT COLOR="#FF0000">"xmit"</FONT>, skb->data, skb->len, 32,is->unit);
|
|
}
|
|
|
|
<FONT COLOR=#A521F7>#ifdef</FONT> CONFIG_ISDN_TIMEOUT_RULES
|
|
(<FONT COLOR="#298C52">void</FONT>)<A HREF="isdn_timru.c.shtml#isdn_net_recalc_timeout">isdn_net_recalc_timeout</A>(<A HREF="../includes/isdn_timru.h.shtml#ISDN_TIMRU_KEEPUP_OUT">ISDN_TIMRU_KEEPUP_OUT</A>,
|
|
<A HREF="../includes/isdn_timru.h.shtml#ISDN_TIMRU_PACKET_PPP">ISDN_TIMRU_PACKET_PPP</A>, &lp->netdev->dev, skb->data, 0);
|
|
<FONT COLOR=#A521F7>#endif</FONT>
|
|
<A HREF="#isdn_ppp_send_ccp">isdn_ppp_send_ccp</A>(lp->netdev,lp,skb); <FONT COLOR=#0000FF>/* keeps CCP/compression states in sync */</FONT>
|
|
|
|
<FONT COLOR="#298C52">if</FONT> ((cnt = <A HREF="isdn_common.c.shtml#isdn_writebuf_skb_stub">isdn_writebuf_skb_stub</A>(lp->isdn_device, lp->isdn_channel, 1, skb)) != count) {
|
|
<FONT COLOR="#298C52">if</FONT> (lp->sav_skb) {
|
|
dev_kfree_skb(lp->sav_skb);
|
|
printk(KERN_INFO <FONT COLOR="#FF0000">"isdn_ppp_write: freeing sav_skb (%d,%d)!\n"</FONT>, cnt, count);
|
|
} <FONT COLOR="#298C52">else</FONT>
|
|
printk(KERN_INFO <FONT COLOR="#FF0000">"isdn_ppp_write: Can't write PPP frame to LL (%d,%d)!\n"</FONT>, cnt, count);
|
|
lp->sav_skb = skb;
|
|
}
|
|
}
|
|
}
|
|
<FONT COLOR="#298C52">return</FONT> count;
|
|
}
|
|
|
|
<FONT COLOR=#0000FF>/*
|
|
* init memory, structures etc.
|
|
*/</FONT>
|
|
|
|
<FONT COLOR="#298C52">int</FONT>
|
|
<A NAME="isdn_ppp_init">isdn_ppp_init</A>(<FONT COLOR="#298C52">void</FONT>)
|
|
{
|
|
<FONT COLOR="#298C52">int</FONT> i,
|
|
j;
|
|
|
|
<FONT COLOR="#298C52">for</FONT> (i = 0; i < <A HREF="../includes/isdn.h.shtml#ISDN_MAX_CHANNELS">ISDN_MAX_CHANNELS</A>; i++) {
|
|
<FONT COLOR="#298C52">if</FONT> (!(ippp_table[i] = (<FONT COLOR="#298C52">struct</FONT> ippp_struct *)
|
|
kmalloc(<FONT COLOR="#298C52">sizeof</FONT>(<FONT COLOR="#298C52">struct</FONT> ippp_struct), GFP_KERNEL))) {
|
|
printk(KERN_WARNING <FONT COLOR="#FF0000">"isdn_ppp_init: Could not alloc ippp_table\n"</FONT>);
|
|
<FONT COLOR="#298C52">for</FONT> (j = 0; j < i; j++)
|
|
kfree(ippp_table[i]);
|
|
<FONT COLOR="#298C52">return</FONT> -1;
|
|
}
|
|
memset((<FONT COLOR="#298C52">char</FONT> *) ippp_table[i], 0, <FONT COLOR="#298C52">sizeof</FONT>(<FONT COLOR="#298C52">struct</FONT> ippp_struct));
|
|
ippp_table[i]->state = 0;
|
|
ippp_table[i]->first = ippp_table[i]->rq + <A HREF="../includes/isdn_ppp.h.shtml#NUM_RCV_BUFFS">NUM_RCV_BUFFS</A> - 1;
|
|
ippp_table[i]->last = ippp_table[i]->rq;
|
|
|
|
<FONT COLOR="#298C52">for</FONT> (j = 0; j < <A HREF="../includes/isdn_ppp.h.shtml#NUM_RCV_BUFFS">NUM_RCV_BUFFS</A>; j++) {
|
|
ippp_table[i]->rq[j].buf = NULL;
|
|
ippp_table[i]->rq[j].last = ippp_table[i]->rq +
|
|
(<A HREF="../includes/isdn_ppp.h.shtml#NUM_RCV_BUFFS">NUM_RCV_BUFFS</A> + j - 1) % <A HREF="../includes/isdn_ppp.h.shtml#NUM_RCV_BUFFS">NUM_RCV_BUFFS</A>;
|
|
ippp_table[i]->rq[j].next = ippp_table[i]->rq + (j + 1) % <A HREF="../includes/isdn_ppp.h.shtml#NUM_RCV_BUFFS">NUM_RCV_BUFFS</A>;
|
|
}
|
|
}
|
|
<FONT COLOR="#298C52">return</FONT> 0;
|
|
}
|
|
|
|
<FONT COLOR="#298C52">void</FONT>
|
|
<A NAME="isdn_ppp_cleanup">isdn_ppp_cleanup</A>(<FONT COLOR="#298C52">void</FONT>)
|
|
{
|
|
<FONT COLOR="#298C52">int</FONT> i;
|
|
|
|
<FONT COLOR="#298C52">for</FONT> (i = 0; i < <A HREF="../includes/isdn.h.shtml#ISDN_MAX_CHANNELS">ISDN_MAX_CHANNELS</A>; i++)
|
|
kfree(ippp_table[i]);
|
|
}
|
|
|
|
<FONT COLOR=#0000FF>/*
|
|
* get the PPP protocol header and pull skb
|
|
*/</FONT>
|
|
<FONT COLOR="#298C52">static</FONT> <FONT COLOR="#298C52">int</FONT> <A HREF="#isdn_ppp_strip_proto">isdn_ppp_strip_proto</A>(<FONT COLOR="#298C52">struct</FONT> sk_buff *skb)
|
|
{
|
|
<FONT COLOR="#298C52">int</FONT> proto;
|
|
<FONT COLOR="#298C52">if</FONT> (skb->data[0] & 0x1) {
|
|
proto = skb->data[0];
|
|
skb_pull(skb, 1); <FONT COLOR=#0000FF>/* protocol ID is only 8 bit */</FONT>
|
|
} <FONT COLOR="#298C52">else</FONT> {
|
|
proto = ((<FONT COLOR="#298C52">int</FONT>) skb->data[0] << 8) + skb->data[1];
|
|
skb_pull(skb, 2);
|
|
}
|
|
<FONT COLOR="#298C52">return</FONT> proto;
|
|
}
|
|
|
|
|
|
<FONT COLOR=#0000FF>/*
|
|
* handler for incoming packets on a syncPPP interface
|
|
*/</FONT>
|
|
<FONT COLOR="#298C52">void</FONT> <A HREF="#isdn_ppp_receive">isdn_ppp_receive</A>(<A HREF="../includes/isdn.h.shtml#isdn_net_dev">isdn_net_dev</A> * net_dev, isdn_net_local * lp, <FONT COLOR="#298C52">struct</FONT> sk_buff *skb)
|
|
{
|
|
<FONT COLOR="#298C52">struct</FONT> ippp_struct *is;
|
|
<FONT COLOR="#298C52">int</FONT> proto;
|
|
|
|
is = ippp_table[lp->ppp_slot];
|
|
|
|
<FONT COLOR="#298C52">if</FONT> (is->debug & 0x4) {
|
|
printk(KERN_DEBUG <FONT COLOR="#FF0000">"ippp_receive: len: %d\n"</FONT>, (<FONT COLOR="#298C52">int</FONT>) skb->len);
|
|
<A HREF="#isdn_ppp_frame_log">isdn_ppp_frame_log</A>(<FONT COLOR="#FF0000">"receive"</FONT>, skb->data, skb->len, 32,is->unit);
|
|
}
|
|
<FONT COLOR="#298C52">if</FONT> (net_dev->local->master) {
|
|
printk(KERN_WARNING <FONT COLOR="#FF0000">"isdn_ppp_receice: net_dev != master\n"</FONT>);
|
|
net_dev = ((isdn_net_local *) net_dev->local->master->priv)->netdev;
|
|
}
|
|
<FONT COLOR="#298C52">if</FONT> (skb->data[0] == 0xff && skb->data[1] == 0x03)
|
|
skb_pull(skb, 2);
|
|
<FONT COLOR="#298C52">else</FONT> <FONT COLOR="#298C52">if</FONT> (is->pppcfg & SC_REJ_COMP_AC) {
|
|
dev_kfree_skb(skb);
|
|
<FONT COLOR="#298C52">return</FONT>; <FONT COLOR=#0000FF>/* discard it silently */</FONT>
|
|
}
|
|
|
|
proto = <A HREF="#isdn_ppp_strip_proto">isdn_ppp_strip_proto</A>(skb);
|
|
|
|
<FONT COLOR=#A521F7>#ifdef</FONT> CONFIG_ISDN_MPP
|
|
<FONT COLOR="#298C52">if</FONT> (!(is->mpppcfg & <A HREF="../includes/isdn_ppp.h.shtml#SC_REJ_MP_PROT">SC_REJ_MP_PROT</A>)) {
|
|
<FONT COLOR="#298C52">int</FONT> sqno_end;
|
|
|
|
<FONT COLOR="#298C52">if</FONT>(is->compflags & <A HREF="../includes/isdn_ppp.h.shtml#SC_LINK_DECOMP_ON">SC_LINK_DECOMP_ON</A>) {
|
|
<FONT COLOR="#298C52">if</FONT>(proto == <A HREF="../includes/isdn_ppp.h.shtml#PPP_LINK_COMP">PPP_LINK_COMP</A>) {
|
|
<FONT COLOR="#298C52">if</FONT>(is->debug & 0x10)
|
|
printk(KERN_DEBUG <FONT COLOR="#FF0000">"received single link compressed frame\n"</FONT>);
|
|
skb = <A HREF="#isdn_ppp_decompress">isdn_ppp_decompress</A>(skb,is,NULL,proto);
|
|
<FONT COLOR="#298C52">if</FONT>(!skb)
|
|
<FONT COLOR="#298C52">return</FONT>;
|
|
proto = <A HREF="#isdn_ppp_strip_proto">isdn_ppp_strip_proto</A>(skb);
|
|
}
|
|
<FONT COLOR="#298C52">else</FONT>
|
|
<A HREF="#isdn_ppp_decompress">isdn_ppp_decompress</A>(skb,is,NULL,proto);
|
|
}
|
|
|
|
<FONT COLOR="#298C52">if</FONT> (proto == <A HREF="../includes/isdn_ppp.h.shtml#PPP_MP">PPP_MP</A>) {
|
|
isdn_net_local *lpq;
|
|
<FONT COLOR="#298C52">long</FONT> sqno, min_sqno, tseq;
|
|
|
|
u_char BEbyte = skb->data[0];
|
|
<FONT COLOR="#298C52">if</FONT> (is->debug & 0x8)
|
|
printk(KERN_DEBUG <FONT COLOR="#FF0000">"recv: %d/%04x/%d -> %02x %02x %02x %02x %02x %02x\n"</FONT>, lp->ppp_slot, proto,
|
|
(<FONT COLOR="#298C52">int</FONT>) skb->len, (<FONT COLOR="#298C52">int</FONT>) skb->data[0], (<FONT COLOR="#298C52">int</FONT>) skb->data[1], (<FONT COLOR="#298C52">int</FONT>) skb->data[2],
|
|
(<FONT COLOR="#298C52">int</FONT>) skb->data[3], (<FONT COLOR="#298C52">int</FONT>) skb->data[4], (<FONT COLOR="#298C52">int</FONT>) skb->data[5]);
|
|
<FONT COLOR="#298C52">if</FONT> (!(is->mpppcfg & <A HREF="../includes/isdn_ppp.h.shtml#SC_IN_SHORT_SEQ">SC_IN_SHORT_SEQ</A>)) {
|
|
sqno = ((<FONT COLOR="#298C52">int</FONT>) skb->data[1] << 16) + ((<FONT COLOR="#298C52">int</FONT>) skb->data[2] << 8) + (<FONT COLOR="#298C52">int</FONT>) skb->data[3];
|
|
skb_pull(skb, 4);
|
|
} <FONT COLOR="#298C52">else</FONT> {
|
|
sqno = (((<FONT COLOR="#298C52">int</FONT>) skb->data[0] & 0xf) << 8) + (<FONT COLOR="#298C52">int</FONT>) skb->data[1];
|
|
skb_pull(skb, 2);
|
|
}
|
|
|
|
<FONT COLOR=#0000FF>/*
|
|
* new sequence number lower than last number? (this is only allowed
|
|
* for overflow case)
|
|
*/</FONT>
|
|
<FONT COLOR="#298C52">if</FONT> ((tseq = is->last_link_seqno) >= sqno) {
|
|
<FONT COLOR="#298C52">int</FONT> range = is->range;
|
|
<FONT COLOR="#298C52">if</FONT> (tseq + 1024 < range + sqno) <FONT COLOR=#0000FF>/* redundancy check .. not MP conform */</FONT>
|
|
printk(KERN_WARNING <FONT COLOR="#FF0000">"isdn_ppp_receive, MP, detected overflow with sqno: %ld, last: %ld !!!\n"</FONT>, sqno, tseq);
|
|
<FONT COLOR="#298C52">else</FONT> {
|
|
sqno += range;
|
|
is->last_link_seqno = sqno;
|
|
}
|
|
} <FONT COLOR="#298C52">else</FONT> {
|
|
<FONT COLOR=#0000FF>/* here, we should also add an redundancy check */</FONT>
|
|
is->last_link_seqno = sqno;
|
|
}
|
|
|
|
<FONT COLOR=#0000FF>/*
|
|
* step over all links to find lowest link number
|
|
*/</FONT>
|
|
<FONT COLOR="#298C52">for</FONT> (min_sqno = LONG_MAX, lpq = net_dev->queue;;) {
|
|
<FONT COLOR="#298C52">long</FONT> lls = ippp_table[lpq->ppp_slot]->last_link_seqno;
|
|
<FONT COLOR="#298C52">if</FONT> (lls >= 0 && lls < min_sqno)
|
|
min_sqno = lls;
|
|
lpq = lpq->next;
|
|
<FONT COLOR="#298C52">if</FONT> (lpq == net_dev->queue)
|
|
<FONT COLOR="#298C52">break</FONT>;
|
|
}
|
|
|
|
<FONT COLOR=#0000FF>/*
|
|
* for the case, that the last frame numbers of all
|
|
* links are overflowed: mask/reduce the sequenece number to
|
|
* 'normal' numbering.
|
|
*/</FONT>
|
|
<FONT COLOR="#298C52">if</FONT> (min_sqno >= ippp_table[lpq->ppp_slot]->range) {
|
|
<FONT COLOR="#298C52">int</FONT> mask = ippp_table[lpq->ppp_slot]->range-1; <FONT COLOR=#0000FF>/* range is power of two, so a mask will do the job */</FONT>
|
|
<A HREF="#isdn_ppp_mask_queue">isdn_ppp_mask_queue</A>(net_dev, mask);
|
|
net_dev->ib.next_num &= mask;
|
|
{
|
|
<FONT COLOR="#298C52">struct</FONT> sqqueue *q = net_dev->ib.sq;
|
|
<FONT COLOR="#298C52">while</FONT> (q) {
|
|
q->sqno_start &= mask;
|
|
q->sqno_end &= mask;
|
|
}
|
|
}
|
|
min_sqno &= mask;
|
|
<FONT COLOR="#298C52">for</FONT> (lpq = net_dev->queue;;) {
|
|
ippp_table[lpq->ppp_slot]->last_link_seqno &= mask;
|
|
lpq = lpq->next;
|
|
<FONT COLOR="#298C52">if</FONT> (lpq == net_dev->queue)
|
|
<FONT COLOR="#298C52">break</FONT>;
|
|
}
|
|
}
|
|
<FONT COLOR="#298C52">if</FONT> ((BEbyte & (<A HREF="../includes/isdn_ppp.h.shtml#MP_BEGIN_FRAG">MP_BEGIN_FRAG</A> | <A HREF="../includes/isdn_ppp.h.shtml#MP_END_FRAG">MP_END_FRAG</A>)) != (<A HREF="../includes/isdn_ppp.h.shtml#MP_BEGIN_FRAG">MP_BEGIN_FRAG</A> | <A HREF="../includes/isdn_ppp.h.shtml#MP_END_FRAG">MP_END_FRAG</A>)) {
|
|
<FONT COLOR="#298C52">static</FONT> <FONT COLOR="#298C52">int</FONT> dmes = 0;
|
|
<FONT COLOR="#298C52">if</FONT>( !dmes ) {
|
|
printk(KERN_DEBUG <FONT COLOR="#FF0000">"ippp: trying ;) to fill mp_queue %d .. UNTESTED!!\n"</FONT>, lp->ppp_slot);
|
|
dmes = 1;
|
|
}
|
|
<FONT COLOR="#298C52">if</FONT> ((sqno_end = <A HREF="#isdn_ppp_fill_mpqueue">isdn_ppp_fill_mpqueue</A>(net_dev, &skb, BEbyte, &sqno, min_sqno)) < 0) {
|
|
net_dev->ib.modify = 1; <FONT COLOR=#0000FF>/* block timeout-timer */</FONT>
|
|
<A HREF="#isdn_ppp_cleanup_sqqueue">isdn_ppp_cleanup_sqqueue</A>(net_dev, lp, min_sqno);
|
|
net_dev->ib.modify = 0;
|
|
<FONT COLOR="#298C52">return</FONT>; <FONT COLOR=#0000FF>/* no packet complete */</FONT>
|
|
}
|
|
} <FONT COLOR="#298C52">else</FONT>
|
|
sqno_end = sqno;
|
|
|
|
<FONT COLOR="#298C52">if</FONT> (is->debug & 0x40)
|
|
printk(KERN_DEBUG <FONT COLOR="#FF0000">"min_sqno: %ld sqno_end %d next: %ld\n"</FONT>, min_sqno, sqno_end, net_dev->ib.next_num);
|
|
|
|
<FONT COLOR=#0000FF>/*
|
|
* MP buffer management .. reorders incoming packets ..
|
|
* lotsa mem-copies and not heavily tested.
|
|
*
|
|
* first check whether there is more than one link in the bundle
|
|
* then check whether the number is in order
|
|
*/</FONT>
|
|
net_dev->ib.modify = 1; <FONT COLOR=#0000FF>/* block timeout-timer */</FONT>
|
|
<FONT COLOR="#298C52">if</FONT> (net_dev->ib.bundled && net_dev->ib.next_num != sqno) {
|
|
<FONT COLOR=#0000FF>/*
|
|
* packet is not 'in order'
|
|
*/</FONT>
|
|
<FONT COLOR="#298C52">struct</FONT> sqqueue *q;
|
|
|
|
q = (<FONT COLOR="#298C52">struct</FONT> sqqueue *) kmalloc(<FONT COLOR="#298C52">sizeof</FONT>(<FONT COLOR="#298C52">struct</FONT> sqqueue), GFP_ATOMIC);
|
|
<FONT COLOR="#298C52">if</FONT> (!q) {
|
|
net_dev->ib.modify = 0;
|
|
printk(KERN_WARNING <FONT COLOR="#FF0000">"ippp/MPPP: Bad! Can't alloc sq node!\n"</FONT>);
|
|
dev_kfree_skb(skb);
|
|
<FONT COLOR="#298C52">return</FONT>; <FONT COLOR=#0000FF>/* discard */</FONT>
|
|
}
|
|
q->skb = skb;
|
|
q->sqno_end = sqno_end;
|
|
q->sqno_start = sqno;
|
|
q->timer = jiffies + (<A HREF="../includes/isdn.h.shtml#ISDN_TIMER_1SEC">ISDN_TIMER_1SEC</A>) * 5; <FONT COLOR=#0000FF>/* timeout after 5 seconds */</FONT>
|
|
|
|
<FONT COLOR="#298C52">if</FONT> (!net_dev->ib.sq) {
|
|
net_dev->ib.sq = q;
|
|
q->next = NULL;
|
|
} <FONT COLOR="#298C52">else</FONT> {
|
|
<FONT COLOR="#298C52">struct</FONT> sqqueue *ql = net_dev->ib.sq;
|
|
<FONT COLOR="#298C52">if</FONT> (ql->sqno_start > q->sqno_start) {
|
|
q->next = ql;
|
|
net_dev->ib.sq = q;
|
|
} <FONT COLOR="#298C52">else</FONT> {
|
|
<FONT COLOR="#298C52">while</FONT> (ql->next && ql->next->sqno_start < q->sqno_start)
|
|
ql = ql->next;
|
|
q->next = ql->next;
|
|
ql->next = q;
|
|
}
|
|
}
|
|
} <FONT COLOR="#298C52">else</FONT> {
|
|
<FONT COLOR=#0000FF>/*
|
|
* packet was 'in order' .. push it higher
|
|
*/</FONT>
|
|
net_dev->ib.next_num = sqno_end + 1;
|
|
proto = <A HREF="#isdn_ppp_strip_proto">isdn_ppp_strip_proto</A>(skb);
|
|
<A HREF="#isdn_ppp_push_higher">isdn_ppp_push_higher</A>(net_dev, lp, skb, proto);
|
|
}
|
|
<A HREF="#isdn_ppp_cleanup_sqqueue">isdn_ppp_cleanup_sqqueue</A>(net_dev, lp, min_sqno);
|
|
net_dev->ib.modify = 0;
|
|
|
|
} <FONT COLOR="#298C52">else</FONT>
|
|
<A HREF="#isdn_ppp_push_higher">isdn_ppp_push_higher</A>(net_dev, lp, skb, proto);
|
|
} <FONT COLOR="#298C52">else</FONT>
|
|
<FONT COLOR=#A521F7>#endif</FONT>
|
|
<A HREF="#isdn_ppp_push_higher">isdn_ppp_push_higher</A>(net_dev, lp, skb, proto);
|
|
}
|
|
|
|
<FONT COLOR=#0000FF>/*
|
|
* push frame to higher layers
|
|
* note: net_dev has to be master net_dev
|
|
*/</FONT>
|
|
<FONT COLOR="#298C52">static</FONT> <FONT COLOR="#298C52">void</FONT>
|
|
<A HREF="#isdn_ppp_push_higher">isdn_ppp_push_higher</A>(<A HREF="../includes/isdn.h.shtml#isdn_net_dev">isdn_net_dev</A> * net_dev, isdn_net_local * lp, <FONT COLOR="#298C52">struct</FONT> sk_buff *skb, <FONT COLOR="#298C52">int</FONT> proto)
|
|
{
|
|
<FONT COLOR="#298C52">struct</FONT> device *dev = &net_dev->dev;
|
|
<FONT COLOR="#298C52">struct</FONT> ippp_struct *is = ippp_table[lp->ppp_slot];
|
|
|
|
<FONT COLOR="#298C52">if</FONT> (is->debug & 0x10) {
|
|
printk(KERN_DEBUG <FONT COLOR="#FF0000">"push, skb %d %04x\n"</FONT>, (<FONT COLOR="#298C52">int</FONT>) skb->len, proto);
|
|
<A HREF="#isdn_ppp_frame_log">isdn_ppp_frame_log</A>(<FONT COLOR="#FF0000">"rpush"</FONT>, skb->data, skb->len, 32,is->unit);
|
|
}
|
|
|
|
<FONT COLOR="#298C52">if</FONT>(proto == PPP_COMP) {
|
|
<FONT COLOR="#298C52">if</FONT>(!lp->master)
|
|
skb = <A HREF="#isdn_ppp_decompress">isdn_ppp_decompress</A>(skb,is,is,proto);
|
|
<FONT COLOR="#298C52">else</FONT>
|
|
skb = <A HREF="#isdn_ppp_decompress">isdn_ppp_decompress</A>(skb,is,ippp_table[((isdn_net_local *) (lp->master->priv))->ppp_slot],proto);
|
|
|
|
<FONT COLOR="#298C52">if</FONT>(!skb) {
|
|
printk(KERN_DEBUG <FONT COLOR="#FF0000">"ippp: compressed frame discarded!\n"</FONT>);
|
|
<FONT COLOR="#298C52">return</FONT>;
|
|
}
|
|
|
|
proto = <A HREF="#isdn_ppp_strip_proto">isdn_ppp_strip_proto</A>(skb);
|
|
<FONT COLOR="#298C52">if</FONT> (is->debug & 0x10) {
|
|
printk(KERN_DEBUG <FONT COLOR="#FF0000">"RPostDecomp, skb %d %04x\n"</FONT>, (<FONT COLOR="#298C52">int</FONT>) skb->len, proto);
|
|
<A HREF="#isdn_ppp_frame_log">isdn_ppp_frame_log</A>(<FONT COLOR="#FF0000">"R-Decomp"</FONT>, skb->data, skb->len, 32,is->unit);
|
|
}
|
|
}
|
|
<FONT COLOR="#298C52">else</FONT> <FONT COLOR="#298C52">if</FONT>(is->compflags & <A HREF="../includes/isdn_ppp.h.shtml#SC_DECOMP_ON">SC_DECOMP_ON</A>) { <FONT COLOR=#0000FF>/* If decomp is ON */</FONT>
|
|
<FONT COLOR="#298C52">if</FONT>(!lp->master)
|
|
<A HREF="#isdn_ppp_decompress">isdn_ppp_decompress</A>(skb,is,is,proto);
|
|
<FONT COLOR="#298C52">else</FONT>
|
|
<A HREF="#isdn_ppp_decompress">isdn_ppp_decompress</A>(skb,is,ippp_table[((isdn_net_local *) (lp->master->priv))->ppp_slot],proto);
|
|
}
|
|
|
|
<FONT COLOR="#298C52">switch</FONT> (proto) {
|
|
<FONT COLOR="#298C52">case</FONT> <A HREF="#PPP_IPX">PPP_IPX</A>: <FONT COLOR=#0000FF>/* untested */</FONT>
|
|
<FONT COLOR="#298C52">if</FONT> (is->debug & 0x20)
|
|
printk(KERN_DEBUG <FONT COLOR="#FF0000">"isdn_ppp: IPX\n"</FONT>);
|
|
skb->dev = dev;
|
|
skb->mac.raw = skb->data;
|
|
skb->protocol = htons(ETH_P_IPX);
|
|
<FONT COLOR="#298C52">break</FONT>;
|
|
<FONT COLOR=#A521F7>#ifdef</FONT> CONFIG_ISDN_PPP_VJ
|
|
<FONT COLOR="#298C52">case</FONT> PPP_VJC_UNCOMP:
|
|
<FONT COLOR="#298C52">if</FONT> (is->debug & 0x20)
|
|
printk(KERN_DEBUG <FONT COLOR="#FF0000">"isdn_ppp: VJC_UNCOMP\n"</FONT>);
|
|
<FONT COLOR="#298C52">if</FONT> (slhc_remember(ippp_table[net_dev->local->ppp_slot]->slcomp, skb->data, skb->len) <= 0) {
|
|
printk(KERN_WARNING <FONT COLOR="#FF0000">"isdn_ppp: received illegal VJC_UNCOMP frame!\n"</FONT>);
|
|
net_dev->local->stats.rx_dropped++;
|
|
dev_kfree_skb(skb);
|
|
<FONT COLOR="#298C52">return</FONT>;
|
|
}
|
|
<FONT COLOR=#A521F7>#endif</FONT>
|
|
<FONT COLOR="#298C52">case</FONT> PPP_IP:
|
|
<FONT COLOR="#298C52">if</FONT> (is->debug & 0x20)
|
|
printk(KERN_DEBUG <FONT COLOR="#FF0000">"isdn_ppp: IP\n"</FONT>);
|
|
skb->dev = dev;
|
|
skb->mac.raw = skb->data;
|
|
skb->protocol = htons(ETH_P_IP);
|
|
<FONT COLOR="#298C52">break</FONT>;
|
|
<FONT COLOR="#298C52">case</FONT> PPP_VJC_COMP:
|
|
<FONT COLOR="#298C52">if</FONT> (is->debug & 0x20)
|
|
printk(KERN_DEBUG <FONT COLOR="#FF0000">"isdn_ppp: VJC_COMP\n"</FONT>);
|
|
<FONT COLOR=#A521F7>#ifdef</FONT> CONFIG_ISDN_PPP_VJ
|
|
{
|
|
<FONT COLOR="#298C52">struct</FONT> sk_buff *skb_old = skb;
|
|
<FONT COLOR="#298C52">int</FONT> pkt_len;
|
|
skb = dev_alloc_skb(skb_old->len + 40);
|
|
|
|
<FONT COLOR="#298C52">if</FONT> (!skb) {
|
|
printk(KERN_WARNING <FONT COLOR="#FF0000">"%s: Memory squeeze, dropping packet.\n"</FONT>, dev-><A HREF="isdn_common.c.shtml#name">name</A>);
|
|
net_dev->local->stats.rx_dropped++;
|
|
dev_kfree_skb(skb_old);
|
|
<FONT COLOR="#298C52">return</FONT>;
|
|
}
|
|
skb->dev = dev;
|
|
skb_put(skb, skb_old->len + 40);
|
|
memcpy(skb->data, skb_old->data, skb_old->len);
|
|
skb->mac.raw = skb->data;
|
|
pkt_len = slhc_uncompress(ippp_table[net_dev->local->ppp_slot]->slcomp,
|
|
skb->data, skb_old->len);
|
|
dev_kfree_skb(skb_old);
|
|
<FONT COLOR="#298C52">if</FONT> (pkt_len < 0) {
|
|
dev_kfree_skb(skb);
|
|
lp->stats.rx_dropped++;
|
|
<FONT COLOR="#298C52">return</FONT>;
|
|
}
|
|
skb_trim(skb, pkt_len);
|
|
skb->protocol = htons(ETH_P_IP);
|
|
}
|
|
<FONT COLOR=#A521F7>#else</FONT>
|
|
printk(KERN_INFO <FONT COLOR="#FF0000">"isdn: Ooopsa .. VJ-Compression support not compiled into isdn driver.\n"</FONT>);
|
|
lp->stats.rx_dropped++;
|
|
dev_kfree_skb(skb);
|
|
<FONT COLOR="#298C52">return</FONT>;
|
|
<FONT COLOR=#A521F7>#endif</FONT>
|
|
<FONT COLOR="#298C52">break</FONT>;
|
|
<FONT COLOR="#298C52">case</FONT> PPP_CCP:
|
|
<FONT COLOR="#298C52">case</FONT> <A HREF="../includes/isdn_ppp.h.shtml#PPP_LINK_CCP">PPP_LINK_CCP</A>:
|
|
<A HREF="#isdn_ppp_receive_ccp">isdn_ppp_receive_ccp</A>(net_dev,lp,skb,proto);
|
|
<FONT COLOR=#0000FF>/* fall through */</FONT>
|
|
<FONT COLOR="#298C52">default</FONT>:
|
|
<FONT COLOR=#A521F7>#ifdef</FONT> CONFIG_ISDN_TIMEOUT_RULES
|
|
(<FONT COLOR="#298C52">void</FONT>)<A HREF="isdn_timru.c.shtml#isdn_net_recalc_timeout">isdn_net_recalc_timeout</A>(<A HREF="../includes/isdn_timru.h.shtml#ISDN_TIMRU_KEEPUP_IN">ISDN_TIMRU_KEEPUP_IN</A>,
|
|
<A HREF="../includes/isdn_timru.h.shtml#ISDN_TIMRU_PACKET_PPP_NO_HEADER">ISDN_TIMRU_PACKET_PPP_NO_HEADER</A>, dev, skb->data, proto);
|
|
<FONT COLOR=#A521F7>#endif</FONT>
|
|
<A HREF="#isdn_ppp_fill_rq">isdn_ppp_fill_rq</A>(skb->data, skb->len, proto, lp->ppp_slot); <FONT COLOR=#0000FF>/* push data to pppd device */</FONT>
|
|
dev_kfree_skb(skb);
|
|
<FONT COLOR="#298C52">return</FONT>;
|
|
}
|
|
|
|
<FONT COLOR=#A521F7>#ifdef</FONT> CONFIG_ISDN_TIMEOUT_RULES
|
|
(<FONT COLOR="#298C52">void</FONT>)<A HREF="isdn_timru.c.shtml#isdn_net_recalc_timeout">isdn_net_recalc_timeout</A>(<A HREF="../includes/isdn_timru.h.shtml#ISDN_TIMRU_KEEPUP_IN">ISDN_TIMRU_KEEPUP_IN</A>,
|
|
<A HREF="../includes/isdn_timru.h.shtml#ISDN_TIMRU_PACKET_SKB">ISDN_TIMRU_PACKET_SKB</A>, dev, skb, 0);
|
|
<FONT COLOR=#A521F7>#else</FONT>
|
|
<FONT COLOR=#0000FF>/* Reset hangup-timer */</FONT>
|
|
lp->huptimer = 0;
|
|
<FONT COLOR=#A521F7>#endif</FONT>
|
|
netif_rx(skb);
|
|
<FONT COLOR=#0000FF>/* net_dev->local->stats.rx_packets++; */</FONT><FONT COLOR=#0000FF>/* done in isdn_net.c */</FONT>
|
|
|
|
<FONT COLOR="#298C52">return</FONT>;
|
|
}
|
|
|
|
<FONT COLOR=#0000FF>/*
|
|
* isdn_ppp_skb_push ..
|
|
* checks whether we have enough space at the beginning of the SKB
|
|
* and allocs a new SKB if necessary
|
|
*/</FONT>
|
|
<FONT COLOR="#298C52">static</FONT> <FONT COLOR="#298C52">unsigned</FONT> <FONT COLOR="#298C52">char</FONT> *<A HREF="#isdn_ppp_skb_push">isdn_ppp_skb_push</A>(<FONT COLOR="#298C52">struct</FONT> sk_buff **skb_p,<FONT COLOR="#298C52">int</FONT> len)
|
|
{
|
|
<FONT COLOR="#298C52">struct</FONT> sk_buff *skb = *skb_p;
|
|
|
|
<FONT COLOR="#298C52">if</FONT>(skb_headroom(skb) < len) {
|
|
printk(KERN_ERR <FONT COLOR="#FF0000">"isdn_ppp_skb_push:under %d %d\n"</FONT>,skb_headroom(skb),len);
|
|
dev_kfree_skb(skb);
|
|
<FONT COLOR="#298C52">return</FONT> NULL;
|
|
}
|
|
<FONT COLOR="#298C52">return</FONT> skb_push(skb,len);
|
|
}
|
|
|
|
|
|
<FONT COLOR=#0000FF>/*
|
|
* send ppp frame .. we expect a PIDCOMPressable proto --
|
|
* (here: currently always PPP_IP,PPP_VJC_COMP,PPP_VJC_UNCOMP)
|
|
*
|
|
* VJ compression may change skb pointer!!! .. requeue with old
|
|
* skb isn't allowed!!
|
|
*/</FONT>
|
|
|
|
<FONT COLOR="#298C52">int</FONT>
|
|
<A HREF="#isdn_ppp_xmit">isdn_ppp_xmit</A>(<FONT COLOR="#298C52">struct</FONT> sk_buff *skb, <FONT COLOR="#298C52">struct</FONT> device *dev)
|
|
{
|
|
<FONT COLOR="#298C52">struct</FONT> device *mdev = ((isdn_net_local *) (dev->priv))->master; <FONT COLOR=#0000FF>/* get master (for redundancy) */</FONT>
|
|
isdn_net_local *lp,*mlp;
|
|
<A HREF="../includes/isdn.h.shtml#isdn_net_dev">isdn_net_dev</A> *nd;
|
|
<FONT COLOR="#298C52">unsigned</FONT> <FONT COLOR="#298C52">int</FONT> proto = PPP_IP; <FONT COLOR=#0000FF>/* 0x21 */</FONT>
|
|
<FONT COLOR="#298C52">struct</FONT> ippp_struct *ipt,*ipts;
|
|
|
|
<FONT COLOR="#298C52">if</FONT> (mdev)
|
|
mlp = (isdn_net_local *) (mdev->priv);
|
|
<FONT COLOR="#298C52">else</FONT> {
|
|
mdev = dev;
|
|
mlp = (isdn_net_local *) (dev->priv);
|
|
}
|
|
nd = mlp->netdev; <FONT COLOR=#0000FF>/* get master lp */</FONT>
|
|
ipts = ippp_table[mlp->ppp_slot];
|
|
|
|
<FONT COLOR="#298C52">if</FONT> (!(ipts->pppcfg & SC_ENABLE_IP)) { <FONT COLOR=#0000FF>/* PPP connected ? */</FONT>
|
|
<FONT COLOR=#A521F7>#ifdef</FONT> ISDN_SYNCPPP_READDRESS
|
|
<FONT COLOR="#298C52">if</FONT> (!ipts->old_pa_addr)
|
|
ipts->old_pa_addr = mdev->pa_addr;
|
|
<FONT COLOR="#298C52">if</FONT> (!ipts->old_pa_dstaddr)
|
|
ipts->old_pa_dstaddr = mdev->pa_dstaddr;
|
|
<FONT COLOR=#A521F7>#endif</FONT>
|
|
<FONT COLOR="#298C52">if</FONT> (ipts->debug & 0x1)
|
|
printk(KERN_INFO <FONT COLOR="#FF0000">"%s: IP frame delayed.\n"</FONT>, dev-><A HREF="isdn_common.c.shtml#name">name</A>);
|
|
<FONT COLOR="#298C52">return</FONT> 1;
|
|
}
|
|
|
|
<FONT COLOR="#298C52">switch</FONT> (ntohs(skb->protocol)) {
|
|
<FONT COLOR="#298C52">case</FONT> ETH_P_IP:
|
|
proto = PPP_IP;
|
|
<FONT COLOR=#A521F7>#ifdef</FONT> ISDN_SYNCPPP_READDRESS
|
|
<FONT COLOR="#298C52">if</FONT> (ipts->old_pa_addr != mdev->pa_addr) {
|
|
<FONT COLOR="#298C52">struct</FONT> iphdr *ipfr;
|
|
ipfr = (<FONT COLOR="#298C52">struct</FONT> iphdr *) skb->data;
|
|
<FONT COLOR="#298C52">if</FONT>(ipts->debug & 0x4)
|
|
printk(KERN_DEBUG <FONT COLOR="#FF0000">"IF-address changed from %lx to %lx\n"</FONT>, ipts->old_pa_addr, mdev->pa_addr);
|
|
<FONT COLOR="#298C52">if</FONT> (ipfr->version == 4) {
|
|
<FONT COLOR="#298C52">if</FONT> (ipfr->saddr == ipts->old_pa_addr) {
|
|
printk(KERN_DEBUG <FONT COLOR="#FF0000">"readdressing %lx to %lx\n"</FONT>, ipfr->saddr, mdev->pa_addr);
|
|
ipfr->saddr = mdev->pa_addr;
|
|
}
|
|
}
|
|
}
|
|
<FONT COLOR=#0000FF>/* dstaddr change not so important */</FONT>
|
|
<FONT COLOR=#A521F7>#endif</FONT>
|
|
<FONT COLOR="#298C52">break</FONT>;
|
|
<FONT COLOR="#298C52">case</FONT> ETH_P_IPX:
|
|
proto = <A HREF="#PPP_IPX">PPP_IPX</A>; <FONT COLOR=#0000FF>/* untested */</FONT>
|
|
<FONT COLOR="#298C52">break</FONT>;
|
|
<FONT COLOR="#298C52">default</FONT>:
|
|
dev_kfree_skb(skb);
|
|
printk(KERN_ERR <FONT COLOR="#FF0000">"isdn_ppp: skipped frame with unsupported protocoll: %#x.\n"</FONT>, skb->protocol);
|
|
<FONT COLOR="#298C52">return</FONT> 0;
|
|
}
|
|
|
|
lp = nd->queue; <FONT COLOR=#0000FF>/* get lp on top of queue */</FONT>
|
|
|
|
<FONT COLOR="#298C52">if</FONT> (lp->sav_skb) { <FONT COLOR=#0000FF>/* find a non-busy device */</FONT>
|
|
isdn_net_local *nlp = lp->next;
|
|
<FONT COLOR="#298C52">while</FONT> (lp->sav_skb) {
|
|
<FONT COLOR="#298C52">if</FONT> (lp == nlp)
|
|
<FONT COLOR="#298C52">return</FONT> 1;
|
|
nlp = nd->queue = nd->queue->next;
|
|
}
|
|
lp = nlp;
|
|
}
|
|
ipt = ippp_table[lp->ppp_slot];
|
|
|
|
<FONT COLOR=#A521F7>#ifndef</FONT> CONFIG_ISDN_TIMEOUT_RULES
|
|
lp->huptimer = 0;
|
|
<FONT COLOR=#A521F7>#endif</FONT>
|
|
|
|
<FONT COLOR=#0000FF>/*
|
|
* after this line .. requeueing in the device queue is no longer allowed!!!
|
|
*/</FONT>
|
|
|
|
<FONT COLOR=#0000FF>/* Pull off the fake header we stuck on earlier to keep
|
|
* the fragemntation code happy.
|
|
* this will break the ISDN_SYNCPPP_READDRESS hack a few lines
|
|
* above. So, enabling this is no longer allowed
|
|
*/</FONT>
|
|
skb_pull(skb,<A HREF="isdn_ppp.h.shtml#IPPP_MAX_HEADER">IPPP_MAX_HEADER</A>);
|
|
|
|
<FONT COLOR="#298C52">if</FONT> (ipt->debug & 0x4)
|
|
printk(KERN_DEBUG <FONT COLOR="#FF0000">"xmit skb, len %d\n"</FONT>, (<FONT COLOR="#298C52">int</FONT>) skb->len);
|
|
<FONT COLOR="#298C52">if</FONT> (ipts->debug & 0x40)
|
|
<A HREF="#isdn_ppp_frame_log">isdn_ppp_frame_log</A>(<FONT COLOR="#FF0000">"xmit0"</FONT>, skb->data, skb->len, 32,ipts->unit);
|
|
|
|
<FONT COLOR=#A521F7>#ifdef</FONT> CONFIG_ISDN_PPP_VJ
|
|
<FONT COLOR="#298C52">if</FONT> (proto == PPP_IP && ipts->pppcfg & SC_COMP_TCP) { <FONT COLOR=#0000FF>/* ipts here? probably yes, but check this again */</FONT>
|
|
<FONT COLOR="#298C52">struct</FONT> sk_buff *new_skb;
|
|
|
|
new_skb = dev_alloc_skb(skb->len);
|
|
<FONT COLOR="#298C52">if</FONT> (new_skb) {
|
|
u_char *buf;
|
|
<FONT COLOR="#298C52">int</FONT> pktlen;
|
|
|
|
new_skb->dev = skb->dev;
|
|
skb_put(new_skb, skb->len);
|
|
buf = skb->data;
|
|
|
|
pktlen = slhc_compress(ipts->slcomp, skb->data, skb->len, new_skb->data,
|
|
&buf, !(ipts->pppcfg & SC_NO_TCP_CCID));
|
|
|
|
<FONT COLOR="#298C52">if</FONT> (buf != skb->data) {
|
|
<FONT COLOR="#298C52">if</FONT> (new_skb->data != buf)
|
|
printk(KERN_ERR <FONT COLOR="#FF0000">"isdn_ppp: FATAL error after slhc_compress!!\n"</FONT>);
|
|
dev_kfree_skb(skb);
|
|
skb = new_skb;
|
|
} <FONT COLOR="#298C52">else</FONT> {
|
|
dev_kfree_skb(new_skb);
|
|
}
|
|
|
|
skb_trim(skb, pktlen);
|
|
<FONT COLOR="#298C52">if</FONT> (skb->data[0] & SL_TYPE_COMPRESSED_TCP) { <FONT COLOR=#0000FF>/* cslip? style -> PPP */</FONT>
|
|
proto = PPP_VJC_COMP;
|
|
skb->data[0] ^= SL_TYPE_COMPRESSED_TCP;
|
|
} <FONT COLOR="#298C52">else</FONT> {
|
|
<FONT COLOR="#298C52">if</FONT> (skb->data[0] >= SL_TYPE_UNCOMPRESSED_TCP)
|
|
proto = PPP_VJC_UNCOMP;
|
|
skb->data[0] = (skb->data[0] & 0x0f) | 0x40;
|
|
}
|
|
}
|
|
}
|
|
<FONT COLOR=#A521F7>#endif</FONT>
|
|
|
|
<FONT COLOR=#0000FF>/*
|
|
* normal (single link) or bundle compression
|
|
*/</FONT>
|
|
<FONT COLOR="#298C52">if</FONT>(ipts->compflags & <A HREF="../includes/isdn_ppp.h.shtml#SC_COMP_ON">SC_COMP_ON</A>)
|
|
skb = <A HREF="#isdn_ppp_compress">isdn_ppp_compress</A>(skb,&proto,ipt,ipts,0);
|
|
|
|
<FONT COLOR="#298C52">if</FONT> (ipt->debug & 0x24)
|
|
printk(KERN_DEBUG <FONT COLOR="#FF0000">"xmit2 skb, len %d, proto %04x\n"</FONT>, (<FONT COLOR="#298C52">int</FONT>) skb->len, proto);
|
|
|
|
<FONT COLOR=#A521F7>#ifdef</FONT> CONFIG_ISDN_MPP
|
|
<FONT COLOR="#298C52">if</FONT> (ipt->mpppcfg & <A HREF="../includes/isdn_ppp.h.shtml#SC_MP_PROT">SC_MP_PROT</A>) {
|
|
<FONT COLOR=#0000FF>/* we get mp_seqno from static isdn_net_local */</FONT>
|
|
<FONT COLOR="#298C52">long</FONT> mp_seqno = ipts->mp_seqno;
|
|
ipts->mp_seqno++;
|
|
nd->queue = nd->queue->next;
|
|
<FONT COLOR="#298C52">if</FONT> (ipt->mpppcfg & <A HREF="../includes/isdn_ppp.h.shtml#SC_OUT_SHORT_SEQ">SC_OUT_SHORT_SEQ</A>) {
|
|
<FONT COLOR="#298C52">unsigned</FONT> <FONT COLOR="#298C52">char</FONT> *data = <A HREF="#isdn_ppp_skb_push">isdn_ppp_skb_push</A>(&skb, 3);
|
|
<FONT COLOR="#298C52">if</FONT>(!data)
|
|
<FONT COLOR="#298C52">return</FONT> 0;
|
|
mp_seqno &= 0xfff;
|
|
data[0] = <A HREF="../includes/isdn_ppp.h.shtml#MP_BEGIN_FRAG">MP_BEGIN_FRAG</A> | <A HREF="../includes/isdn_ppp.h.shtml#MP_END_FRAG">MP_END_FRAG</A> | ((mp_seqno >> 8) & 0xf); <FONT COLOR=#0000FF>/* (B)egin & (E)ndbit .. */</FONT>
|
|
data[1] = mp_seqno & 0xff;
|
|
data[2] = proto; <FONT COLOR=#0000FF>/* PID compression */</FONT>
|
|
} <FONT COLOR="#298C52">else</FONT> {
|
|
<FONT COLOR="#298C52">unsigned</FONT> <FONT COLOR="#298C52">char</FONT> *data = <A HREF="#isdn_ppp_skb_push">isdn_ppp_skb_push</A>(&skb, 5);
|
|
<FONT COLOR="#298C52">if</FONT>(!data)
|
|
<FONT COLOR="#298C52">return</FONT> 0;
|
|
data[0] = <A HREF="../includes/isdn_ppp.h.shtml#MP_BEGIN_FRAG">MP_BEGIN_FRAG</A> | <A HREF="../includes/isdn_ppp.h.shtml#MP_END_FRAG">MP_END_FRAG</A>; <FONT COLOR=#0000FF>/* (B)egin & (E)ndbit .. */</FONT>
|
|
data[1] = (mp_seqno >> 16) & 0xff; <FONT COLOR=#0000FF>/* sequence number: 24bit */</FONT>
|
|
data[2] = (mp_seqno >> 8) & 0xff;
|
|
data[3] = (mp_seqno >> 0) & 0xff;
|
|
data[4] = proto; <FONT COLOR=#0000FF>/* PID compression */</FONT>
|
|
}
|
|
proto = <A HREF="../includes/isdn_ppp.h.shtml#PPP_MP">PPP_MP</A>; <FONT COLOR=#0000FF>/* MP Protocol, 0x003d */</FONT>
|
|
}
|
|
<FONT COLOR=#A521F7>#endif</FONT>
|
|
|
|
<FONT COLOR=#0000FF>/*
|
|
* 'link in bundle' compression ...
|
|
*/</FONT>
|
|
<FONT COLOR="#298C52">if</FONT>(ipt->compflags & <A HREF="../includes/isdn_ppp.h.shtml#SC_LINK_COMP_ON">SC_LINK_COMP_ON</A>)
|
|
skb = <A HREF="#isdn_ppp_compress">isdn_ppp_compress</A>(skb,&proto,ipt,ipts,1);
|
|
|
|
<FONT COLOR="#298C52">if</FONT>( (ipt->pppcfg & SC_COMP_PROT) && (proto <= 0xff) ) {
|
|
<FONT COLOR="#298C52">unsigned</FONT> <FONT COLOR="#298C52">char</FONT> *data = <A HREF="#isdn_ppp_skb_push">isdn_ppp_skb_push</A>(&skb,1);
|
|
<FONT COLOR="#298C52">if</FONT>(!data)
|
|
<FONT COLOR="#298C52">return</FONT> 0;
|
|
data[0] = proto & 0xff;
|
|
}
|
|
<FONT COLOR="#298C52">else</FONT> {
|
|
<FONT COLOR="#298C52">unsigned</FONT> <FONT COLOR="#298C52">char</FONT> *data = <A HREF="#isdn_ppp_skb_push">isdn_ppp_skb_push</A>(&skb,2);
|
|
<FONT COLOR="#298C52">if</FONT>(!data)
|
|
<FONT COLOR="#298C52">return</FONT> 0;
|
|
data[0] = (proto >> 8) & 0xff;
|
|
data[1] = proto & 0xff;
|
|
}
|
|
<FONT COLOR="#298C52">if</FONT>(!(ipt->pppcfg & SC_COMP_AC)) {
|
|
<FONT COLOR="#298C52">unsigned</FONT> <FONT COLOR="#298C52">char</FONT> *data = <A HREF="#isdn_ppp_skb_push">isdn_ppp_skb_push</A>(&skb,2);
|
|
<FONT COLOR="#298C52">if</FONT>(!data)
|
|
<FONT COLOR="#298C52">return</FONT> 0;
|
|
data[0] = 0xff; <FONT COLOR=#0000FF>/* All Stations */</FONT>
|
|
data[1] = 0x03; <FONT COLOR=#0000FF>/* Unnumbered information */</FONT>
|
|
}
|
|
|
|
<FONT COLOR=#0000FF>/* tx-stats are now updated via BSENT-callback */</FONT>
|
|
|
|
<FONT COLOR="#298C52">if</FONT> (ipts->debug & 0x40) {
|
|
printk(KERN_DEBUG <FONT COLOR="#FF0000">"skb xmit: len: %d\n"</FONT>, (<FONT COLOR="#298C52">int</FONT>) skb->len);
|
|
<A HREF="#isdn_ppp_frame_log">isdn_ppp_frame_log</A>(<FONT COLOR="#FF0000">"xmit"</FONT>, skb->data, skb->len, 32,ipts->unit);
|
|
}
|
|
<FONT COLOR="#298C52">if</FONT> (<A HREF="isdn_net.c.shtml#isdn_net_send_skb">isdn_net_send_skb</A>(dev, lp, skb)) {
|
|
<FONT COLOR="#298C52">if</FONT> (lp->sav_skb) { <FONT COLOR=#0000FF>/* whole sav_skb processing with disabled IRQs ?? */</FONT>
|
|
printk(KERN_ERR <FONT COLOR="#FF0000">"%s: whoops .. there is another stored skb!\n"</FONT>, dev-><A HREF="isdn_common.c.shtml#name">name</A>);
|
|
dev_kfree_skb(skb);
|
|
} <FONT COLOR="#298C52">else</FONT>
|
|
lp->sav_skb = skb;
|
|
}
|
|
<FONT COLOR="#298C52">return</FONT> 0;
|
|
}
|
|
|
|
<FONT COLOR=#A521F7>#ifdef</FONT> CONFIG_ISDN_MPP
|
|
|
|
<FONT COLOR=#0000FF>/*
|
|
* free SQ queue
|
|
* -------------
|
|
* Note: We need two queues for MPPP. The SQ queue holds fully (re)assembled frames,
|
|
* that can't be delivered, because there is an outstanding earlier frame
|
|
*/</FONT>
|
|
<FONT COLOR="#298C52">static</FONT> <FONT COLOR="#298C52">void</FONT>
|
|
<A NAME="isdn_ppp_free_sqqueue">isdn_ppp_free_sqqueue</A>(<A HREF="../includes/isdn.h.shtml#isdn_net_dev">isdn_net_dev</A> * p)
|
|
{
|
|
<FONT COLOR="#298C52">struct</FONT> sqqueue *q = p->ib.sq;
|
|
|
|
p->ib.sq = NULL;
|
|
<FONT COLOR="#298C52">while</FONT> (q) {
|
|
<FONT COLOR="#298C52">struct</FONT> sqqueue *qn = q->next;
|
|
<FONT COLOR="#298C52">if</FONT> (q->skb)
|
|
dev_kfree_skb(q->skb);
|
|
kfree(q);
|
|
q = qn;
|
|
}
|
|
|
|
}
|
|
|
|
<FONT COLOR=#0000FF>/*
|
|
* free MP queue
|
|
* -------------
|
|
* Note: The MP queue holds all frame fragments of frames, that can't be
|
|
* reassembled, because there is at least one missing fragment.
|
|
*/</FONT>
|
|
<FONT COLOR="#298C52">static</FONT> <FONT COLOR="#298C52">void</FONT>
|
|
<A NAME="isdn_ppp_free_mpqueue">isdn_ppp_free_mpqueue</A>(<A HREF="../includes/isdn.h.shtml#isdn_net_dev">isdn_net_dev</A> * p)
|
|
{
|
|
<FONT COLOR="#298C52">struct</FONT> mpqueue *q = p->mp_last;
|
|
p->mp_last = NULL;
|
|
|
|
<FONT COLOR="#298C52">while</FONT> (q) {
|
|
<FONT COLOR="#298C52">struct</FONT> mpqueue *ql = q->next;
|
|
dev_kfree_skb(q->skb);
|
|
kfree(q);
|
|
q = ql;
|
|
}
|
|
}
|
|
|
|
<FONT COLOR="#298C52">static</FONT> <FONT COLOR="#298C52">int</FONT>
|
|
<A NAME="isdn_ppp_bundle">isdn_ppp_bundle</A>(<FONT COLOR="#298C52">struct</FONT> ippp_struct *is, <FONT COLOR="#298C52">int</FONT> unit)
|
|
{
|
|
<FONT COLOR="#298C52">char</FONT> ifn[IFNAMSIZ + 1];
|
|
<FONT COLOR="#298C52">long</FONT> flags;
|
|
<A HREF="../includes/isdn.h.shtml#isdn_net_dev">isdn_net_dev</A> *p;
|
|
isdn_net_local *lp,
|
|
*nlp;
|
|
|
|
sprintf(ifn, <FONT COLOR="#FF0000">"ippp%d"</FONT>, unit);
|
|
p = <A HREF="isdn_net.c.shtml#isdn_net_findif">isdn_net_findif</A>(ifn);
|
|
<FONT COLOR="#298C52">if</FONT> (!p)
|
|
<FONT COLOR="#298C52">return</FONT> -1;
|
|
|
|
<A HREF="isdn_common.c.shtml#isdn_timer_ctrl">isdn_timer_ctrl</A>(<A HREF="../includes/isdn.h.shtml#ISDN_TIMER_IPPP">ISDN_TIMER_IPPP</A>, 1); <FONT COLOR=#0000FF>/* enable timer for ippp/MP */</FONT>
|
|
|
|
save_flags(flags);
|
|
<A HREF="kdebug.h.shtml#cli">cli</A>();
|
|
|
|
nlp = is->lp;
|
|
|
|
lp = p->queue;
|
|
p->ib.bundled = 1;
|
|
nlp->last = lp->last;
|
|
lp->last->next = nlp;
|
|
lp->last = nlp;
|
|
nlp->next = lp;
|
|
p->queue = nlp;
|
|
|
|
ippp_table[nlp->ppp_slot]->unit = ippp_table[lp->ppp_slot]->unit;
|
|
<FONT COLOR=#0000FF>/* maybe also SC_CCP stuff */</FONT>
|
|
ippp_table[nlp->ppp_slot]->pppcfg |= ippp_table[lp->ppp_slot]->pppcfg &
|
|
(SC_ENABLE_IP | SC_NO_TCP_CCID | SC_REJ_COMP_TCP);
|
|
|
|
ippp_table[nlp->ppp_slot]->mpppcfg |= ippp_table[lp->ppp_slot]->mpppcfg &
|
|
(<A HREF="../includes/isdn_ppp.h.shtml#SC_MP_PROT">SC_MP_PROT</A> | <A HREF="../includes/isdn_ppp.h.shtml#SC_REJ_MP_PROT">SC_REJ_MP_PROT</A> | <A HREF="../includes/isdn_ppp.h.shtml#SC_OUT_SHORT_SEQ">SC_OUT_SHORT_SEQ</A> | <A HREF="../includes/isdn_ppp.h.shtml#SC_IN_SHORT_SEQ">SC_IN_SHORT_SEQ</A>);
|
|
<FONT COLOR=#A521F7>#if</FONT> 0
|
|
<FONT COLOR="#298C52">if</FONT> (ippp_table[nlp->ppp_slot]->mpppcfg != ippp_table[lp->ppp_slot]->mpppcfg) {
|
|
printk(KERN_WARNING <FONT COLOR="#FF0000">"isdn_ppp_bundle: different MP options %04x and %04x\n"</FONT>,
|
|
ippp_table[nlp->ppp_slot]->mpppcfg, ippp_table[lp->ppp_slot]->mpppcfg);
|
|
}
|
|
<FONT COLOR=#A521F7>#endif</FONT>
|
|
|
|
<A HREF="kdebug.h.shtml#restore_flags">restore_flags</A>(flags);
|
|
<FONT COLOR="#298C52">return</FONT> 0;
|
|
}
|
|
|
|
<FONT COLOR=#0000FF>/*
|
|
* Mask sequence numbers in MP queue
|
|
*/</FONT>
|
|
<FONT COLOR="#298C52">static</FONT> <FONT COLOR="#298C52">void</FONT>
|
|
<A HREF="#isdn_ppp_mask_queue">isdn_ppp_mask_queue</A>(<A HREF="../includes/isdn.h.shtml#isdn_net_dev">isdn_net_dev</A> * dev, <FONT COLOR="#298C52">long</FONT> mask)
|
|
{
|
|
<FONT COLOR="#298C52">struct</FONT> mpqueue *q = dev->mp_last;
|
|
<FONT COLOR="#298C52">while</FONT> (q) {
|
|
q->sqno &= mask;
|
|
q = q->next;
|
|
}
|
|
}
|
|
|
|
<FONT COLOR=#0000FF>/*
|
|
* put a fragment at the right place into the MP queue
|
|
* Also checks, whether this fragment completes a frame. In this case
|
|
* the fragments are copied together into one SKB
|
|
*/</FONT>
|
|
<FONT COLOR="#298C52">static</FONT> <FONT COLOR="#298C52">int</FONT>
|
|
<A HREF="#isdn_ppp_fill_mpqueue">isdn_ppp_fill_mpqueue</A>(<A HREF="../includes/isdn.h.shtml#isdn_net_dev">isdn_net_dev</A> * dev, <FONT COLOR="#298C52">struct</FONT> sk_buff **skb, <FONT COLOR="#298C52">int</FONT> BEbyte, <FONT COLOR="#298C52">long</FONT> *sqnop, <FONT COLOR="#298C52">int</FONT> min_sqno)
|
|
{
|
|
<FONT COLOR="#298C52">struct</FONT> mpqueue *qe,
|
|
*q1,
|
|
*q;
|
|
<FONT COLOR="#298C52">long</FONT> cnt,
|
|
flags;
|
|
<FONT COLOR="#298C52">int</FONT> pktlen,
|
|
sqno_end;
|
|
<FONT COLOR="#298C52">int</FONT> sqno = *sqnop;
|
|
|
|
q1 = (<FONT COLOR="#298C52">struct</FONT> mpqueue *) kmalloc(<FONT COLOR="#298C52">sizeof</FONT>(<FONT COLOR="#298C52">struct</FONT> mpqueue), GFP_ATOMIC);
|
|
<FONT COLOR="#298C52">if</FONT> (!q1) {
|
|
printk(KERN_WARNING <FONT COLOR="#FF0000">"isdn_ppp_fill_mpqueue: Can't alloc struct memory.\n"</FONT>);
|
|
save_flags(flags);
|
|
<A HREF="kdebug.h.shtml#cli">cli</A>();
|
|
<A HREF="#isdn_ppp_cleanup_mpqueue">isdn_ppp_cleanup_mpqueue</A>(dev, min_sqno);
|
|
<A HREF="kdebug.h.shtml#restore_flags">restore_flags</A>(flags);
|
|
<FONT COLOR="#298C52">return</FONT> -1;
|
|
}
|
|
q1->skb = *skb;
|
|
q1->sqno = sqno;
|
|
q1->BEbyte = BEbyte;
|
|
q1->time = jiffies;
|
|
|
|
save_flags(flags);
|
|
<A HREF="kdebug.h.shtml#cli">cli</A>();
|
|
|
|
<FONT COLOR="#298C52">if</FONT> (!(q = dev->mp_last)) {
|
|
dev->mp_last = q1;
|
|
q1->next = NULL;
|
|
q1->last = NULL;
|
|
<A HREF="#isdn_ppp_cleanup_mpqueue">isdn_ppp_cleanup_mpqueue</A>(dev, min_sqno); <FONT COLOR=#0000FF>/* not necessary */</FONT>
|
|
<A HREF="kdebug.h.shtml#restore_flags">restore_flags</A>(flags);
|
|
<FONT COLOR="#298C52">return</FONT> -1; <FONT COLOR=#0000FF>/* -1 is not an error. Just says, that this fragment hasn't complete a full frame */</FONT>
|
|
}
|
|
<FONT COLOR="#298C52">for</FONT> (;;) { <FONT COLOR=#0000FF>/* the faster way would be to step from the queue-end to the start */</FONT>
|
|
<FONT COLOR="#298C52">if</FONT> (sqno > q->sqno) {
|
|
<FONT COLOR="#298C52">if</FONT> (q->next) {
|
|
q = q->next;
|
|
<FONT COLOR="#298C52">continue</FONT>;
|
|
}
|
|
q->next = q1;
|
|
q1->next = NULL;
|
|
q1->last = q;
|
|
<FONT COLOR="#298C52">break</FONT>;
|
|
}
|
|
<FONT COLOR="#298C52">if</FONT> (sqno == q->sqno)
|
|
printk(KERN_WARNING <FONT COLOR="#FF0000">"isdn_fill_mpqueue: illegal sqno received!!\n"</FONT>);
|
|
q1->last = q->last;
|
|
q1->next = q;
|
|
<FONT COLOR="#298C52">if</FONT> (q->last) {
|
|
q->last->next = q1;
|
|
} <FONT COLOR="#298C52">else</FONT>
|
|
dev->mp_last = q1;
|
|
q->last = q1;
|
|
<FONT COLOR="#298C52">break</FONT>;
|
|
}
|
|
|
|
<FONT COLOR=#0000FF>/* now we check whether we completed a packet with this fragment */</FONT>
|
|
pktlen = -q1->skb->len;
|
|
q = q1;
|
|
cnt = q1->sqno;
|
|
<FONT COLOR="#298C52">while</FONT> (!(q->BEbyte & <A HREF="../includes/isdn_ppp.h.shtml#MP_END_FRAG">MP_END_FRAG</A>)) {
|
|
cnt++;
|
|
<FONT COLOR="#298C52">if</FONT> (!(q->next) || q->next->sqno != cnt) {
|
|
<A HREF="#isdn_ppp_cleanup_mpqueue">isdn_ppp_cleanup_mpqueue</A>(dev, min_sqno);
|
|
<A HREF="kdebug.h.shtml#restore_flags">restore_flags</A>(flags);
|
|
<FONT COLOR="#298C52">return</FONT> -1;
|
|
}
|
|
pktlen += q->skb->len;
|
|
q = q->next;
|
|
}
|
|
pktlen += q->skb->len;
|
|
qe = q;
|
|
|
|
q = q1;
|
|
cnt = q1->sqno;
|
|
<FONT COLOR="#298C52">while</FONT> (!(q->BEbyte & <A HREF="../includes/isdn_ppp.h.shtml#MP_BEGIN_FRAG">MP_BEGIN_FRAG</A>)) {
|
|
cnt--;
|
|
<FONT COLOR="#298C52">if</FONT> (!(q->last) || q->last->sqno != cnt) {
|
|
<A HREF="#isdn_ppp_cleanup_mpqueue">isdn_ppp_cleanup_mpqueue</A>(dev, min_sqno);
|
|
<A HREF="kdebug.h.shtml#restore_flags">restore_flags</A>(flags);
|
|
<FONT COLOR="#298C52">return</FONT> -1;
|
|
}
|
|
pktlen += q->skb->len;
|
|
q = q->last;
|
|
}
|
|
pktlen += q->skb->len;
|
|
|
|
<FONT COLOR="#298C52">if</FONT> (q->last)
|
|
q->last->next = qe->next;
|
|
<FONT COLOR="#298C52">else</FONT>
|
|
dev->mp_last = qe->next;
|
|
|
|
<FONT COLOR="#298C52">if</FONT> (qe->next)
|
|
qe->next->last = q->last;
|
|
qe->next = NULL;
|
|
sqno_end = qe->sqno;
|
|
*sqnop = q->sqno;
|
|
|
|
<A HREF="#isdn_ppp_cleanup_mpqueue">isdn_ppp_cleanup_mpqueue</A>(dev, min_sqno);
|
|
<A HREF="kdebug.h.shtml#restore_flags">restore_flags</A>(flags);
|
|
|
|
*skb = dev_alloc_skb(pktlen + 40); <FONT COLOR=#0000FF>/* not needed: +40 for VJ compression .. */</FONT>
|
|
|
|
<FONT COLOR="#298C52">if</FONT> (!(*skb)) {
|
|
<FONT COLOR="#298C52">while</FONT> (q) {
|
|
<FONT COLOR="#298C52">struct</FONT> mpqueue *ql = q->next;
|
|
dev_kfree_skb(q->skb);
|
|
kfree(q);
|
|
q = ql;
|
|
}
|
|
<FONT COLOR="#298C52">return</FONT> -2;
|
|
}
|
|
cnt = 0;
|
|
skb_put(*skb, pktlen);
|
|
<FONT COLOR="#298C52">while</FONT> (q) {
|
|
<FONT COLOR="#298C52">struct</FONT> mpqueue *ql = q->next;
|
|
memcpy((*skb)->data + cnt, q->skb->data, q->skb->len);
|
|
cnt += q->skb->len;
|
|
dev_kfree_skb(q->skb);
|
|
kfree(q);
|
|
q = ql;
|
|
}
|
|
|
|
<FONT COLOR="#298C52">return</FONT> sqno_end;
|
|
}
|
|
|
|
<FONT COLOR=#0000FF>/*
|
|
* check sq-queue, whether we have still buffered the next packet(s)
|
|
* or packets with a sqno less or equal to min_sqno
|
|
* net_dev: master netdevice , lp: 'real' local connection
|
|
*/</FONT>
|
|
<FONT COLOR="#298C52">static</FONT> <FONT COLOR="#298C52">void</FONT>
|
|
<A HREF="#isdn_ppp_cleanup_sqqueue">isdn_ppp_cleanup_sqqueue</A>(<A HREF="../includes/isdn.h.shtml#isdn_net_dev">isdn_net_dev</A> * net_dev, isdn_net_local * lp, <FONT COLOR="#298C52">long</FONT> min_sqno)
|
|
{
|
|
<FONT COLOR="#298C52">struct</FONT> sqqueue *q;
|
|
|
|
<FONT COLOR="#298C52">while</FONT> ((q = net_dev->ib.sq) && (q->sqno_start == net_dev->ib.next_num || q->sqno_end <= min_sqno)) {
|
|
<FONT COLOR="#298C52">int</FONT> proto;
|
|
<FONT COLOR="#298C52">if</FONT> (q->sqno_start != net_dev->ib.next_num) {
|
|
printk(KERN_DEBUG <FONT COLOR="#FF0000">"ippp: MP, stepping over missing frame: %ld\n"</FONT>, net_dev->ib.next_num);
|
|
<FONT COLOR=#A521F7>#ifdef</FONT> CONFIG_ISDN_PPP_VJ
|
|
slhc_toss(ippp_table[net_dev->local->ppp_slot]->slcomp);
|
|
<FONT COLOR=#A521F7>#endif</FONT>
|
|
}
|
|
proto = <A HREF="#isdn_ppp_strip_proto">isdn_ppp_strip_proto</A>(q->skb);
|
|
<A HREF="#isdn_ppp_push_higher">isdn_ppp_push_higher</A>(net_dev, lp, q->skb, proto);
|
|
net_dev->ib.sq = q->next;
|
|
net_dev->ib.next_num = q->sqno_end + 1;
|
|
kfree(q);
|
|
}
|
|
}
|
|
|
|
<FONT COLOR=#0000FF>/*
|
|
* remove stale packets from list
|
|
*/</FONT>
|
|
<FONT COLOR="#298C52">static</FONT> <FONT COLOR="#298C52">void</FONT>
|
|
<A HREF="#isdn_ppp_cleanup_mpqueue">isdn_ppp_cleanup_mpqueue</A>(<A HREF="../includes/isdn.h.shtml#isdn_net_dev">isdn_net_dev</A> * dev, <FONT COLOR="#298C52">long</FONT> min_sqno)
|
|
{
|
|
<FONT COLOR=#A521F7>#ifdef</FONT> CONFIG_ISDN_PPP_VJ
|
|
<FONT COLOR="#298C52">int</FONT> toss = 0;
|
|
<FONT COLOR=#A521F7>#endif</FONT>
|
|
<FONT COLOR=#0000FF>/* z.z einfaches aussortieren gammeliger pakete. Fuer die Zukunft:
|
|
eventuell, solange vorne kein B-paket ist und sqno<=min_sqno: auch rauswerfen
|
|
wenn sqno<min_sqno und Luecken vorhanden sind: auch weg (die koennen nicht mehr gefuellt werden)
|
|
bei paketen groesser min_sqno: ueber mp_mrru: wenn summe ueber pktlen der rumhaengenden Pakete
|
|
groesser als mrru ist: raus damit , Pakete muessen allerdings zusammenhaengen sonst koennte
|
|
ja ein Paket mit B und eins mit E dazwischenpassen */</FONT>
|
|
|
|
<FONT COLOR="#298C52">struct</FONT> mpqueue *ql,
|
|
*q = dev->mp_last;
|
|
<FONT COLOR="#298C52">while</FONT>(q && (q->sqno < min_sqno) ) {
|
|
<FONT COLOR="#298C52">if</FONT> ( (q->BEbyte & <A HREF="../includes/isdn_ppp.h.shtml#MP_END_FRAG">MP_END_FRAG</A>) ||
|
|
(q->next && (q->next->sqno <= min_sqno) && (q->next->BEbyte & <A HREF="../includes/isdn_ppp.h.shtml#MP_BEGIN_FRAG">MP_BEGIN_FRAG</A>)) ) {
|
|
printk(KERN_DEBUG <FONT COLOR="#FF0000">"ippp: freeing stale packet(s), min_sq: %ld!\n"</FONT>,min_sqno);
|
|
<FONT COLOR="#298C52">if</FONT> ((dev->mp_last = q->next))
|
|
q->next->last = NULL;
|
|
<FONT COLOR="#298C52">while</FONT> (q) {
|
|
ql = q->last;
|
|
printk(KERN_DEBUG <FONT COLOR="#FF0000">"ippp, freeing packet with sqno: %ld\n"</FONT>,q->sqno);
|
|
dev_kfree_skb(q->skb);
|
|
kfree(q);
|
|
<FONT COLOR=#A521F7>#ifdef</FONT> CONFIG_ISDN_PPP_VJ
|
|
toss = 1;
|
|
<FONT COLOR=#A521F7>#endif</FONT>
|
|
q = ql;
|
|
}
|
|
q = dev->mp_last;
|
|
} <FONT COLOR="#298C52">else</FONT>
|
|
q = q->next;
|
|
}
|
|
<FONT COLOR=#A521F7>#ifdef</FONT> CONFIG_ISDN_PPP_VJ
|
|
<FONT COLOR=#0000FF>/* did we free a stale frame ? */</FONT>
|
|
<FONT COLOR="#298C52">if</FONT> (toss)
|
|
slhc_toss(ippp_table[dev->local->ppp_slot]->slcomp);
|
|
<FONT COLOR=#A521F7>#endif</FONT>
|
|
}
|
|
<FONT COLOR=#A521F7>#endif</FONT>
|
|
|
|
<FONT COLOR=#0000FF>/*
|
|
* a buffered packet timed-out?
|
|
*/</FONT>
|
|
<FONT COLOR="#298C52">void</FONT>
|
|
<A NAME="isdn_ppp_timer_timeout">isdn_ppp_timer_timeout</A>(<FONT COLOR="#298C52">void</FONT>)
|
|
{
|
|
<FONT COLOR=#A521F7>#ifdef</FONT> CONFIG_ISDN_MPP
|
|
<A HREF="../includes/isdn.h.shtml#isdn_net_dev">isdn_net_dev</A> *net_dev = dev->netdev;
|
|
<FONT COLOR="#298C52">struct</FONT> sqqueue *q,
|
|
*ql = NULL,
|
|
*qn;
|
|
|
|
<FONT COLOR="#298C52">while</FONT> (net_dev) {
|
|
isdn_net_local *lp = net_dev->local;
|
|
<FONT COLOR="#298C52">if</FONT> (net_dev->ib.modify || lp->master) { <FONT COLOR=#0000FF>/* interface locked or slave? */</FONT>
|
|
net_dev = net_dev->next;
|
|
<FONT COLOR="#298C52">continue</FONT>;
|
|
}
|
|
q = net_dev->ib.sq;
|
|
<FONT COLOR="#298C52">while</FONT> (q) {
|
|
<FONT COLOR="#298C52">if</FONT> (q->sqno_start == net_dev->ib.next_num || q->timer < jiffies) {
|
|
|
|
<FONT COLOR=#A521F7>#ifdef</FONT> CONFIG_ISDN_PPP_VJ
|
|
<FONT COLOR=#0000FF>/* did we step over a missing frame ? */</FONT>
|
|
<FONT COLOR="#298C52">if</FONT> (q->sqno_start != net_dev->ib.next_num)
|
|
slhc_toss(ippp_table[lp->ppp_slot]->slcomp);
|
|
<FONT COLOR=#A521F7>#endif</FONT>
|
|
|
|
ql = net_dev->ib.sq;
|
|
net_dev->ib.sq = q->next;
|
|
net_dev->ib.next_num = q->sqno_end + 1;
|
|
q->next = NULL;
|
|
<FONT COLOR="#298C52">for</FONT> (; ql;) {
|
|
<FONT COLOR="#298C52">int</FONT> proto = <A HREF="#isdn_ppp_strip_proto">isdn_ppp_strip_proto</A>(ql->skb);
|
|
<A HREF="#isdn_ppp_push_higher">isdn_ppp_push_higher</A>(net_dev, lp, ql->skb, proto);
|
|
qn = ql->next;
|
|
kfree(ql);
|
|
ql = qn;
|
|
}
|
|
q = net_dev->ib.sq;
|
|
} <FONT COLOR="#298C52">else</FONT>
|
|
q = q->next;
|
|
}
|
|
net_dev = net_dev->next;
|
|
}
|
|
<FONT COLOR=#A521F7>#endif</FONT>
|
|
}
|
|
|
|
<FONT COLOR=#0000FF>/*
|
|
* network device ioctl handlers
|
|
*/</FONT>
|
|
|
|
<FONT COLOR="#298C52">static</FONT> <FONT COLOR="#298C52">int</FONT>
|
|
<A HREF="#isdn_ppp_dev_ioctl_stats">isdn_ppp_dev_ioctl_stats</A>(<FONT COLOR="#298C52">int</FONT> slot, <FONT COLOR="#298C52">struct</FONT> ifreq *ifr, <FONT COLOR="#298C52">struct</FONT> device *dev)
|
|
{
|
|
<FONT COLOR="#298C52">struct</FONT> ppp_stats *res,
|
|
t;
|
|
isdn_net_local *lp = (isdn_net_local *) dev->priv;
|
|
<FONT COLOR="#298C52">int</FONT> err;
|
|
|
|
res = (<FONT COLOR="#298C52">struct</FONT> ppp_stats *) ifr->ifr_ifru.ifru_data;
|
|
err = verify_area(VERIFY_WRITE, res, <FONT COLOR="#298C52">sizeof</FONT>(<FONT COLOR="#298C52">struct</FONT> ppp_stats));
|
|
|
|
<FONT COLOR="#298C52">if</FONT> (err)
|
|
<FONT COLOR="#298C52">return</FONT> err;
|
|
|
|
<FONT COLOR=#0000FF>/* build a temporary stat struct and copy it to user space */</FONT>
|
|
|
|
memset(&t, 0, <FONT COLOR="#298C52">sizeof</FONT>(<FONT COLOR="#298C52">struct</FONT> ppp_stats));
|
|
<FONT COLOR="#298C52">if</FONT> (dev->flags & IFF_UP) {
|
|
t.p.ppp_ipackets = lp->stats.rx_packets;
|
|
t.p.ppp_ierrors = lp->stats.rx_errors;
|
|
t.p.ppp_opackets = lp->stats.tx_packets;
|
|
t.p.ppp_oerrors = lp->stats.tx_errors;
|
|
<FONT COLOR=#A521F7>#ifdef</FONT> CONFIG_ISDN_PPP_VJ
|
|
<FONT COLOR="#298C52">if</FONT> (slot >= 0 && ippp_table[slot]->slcomp) {
|
|
<FONT COLOR="#298C52">struct</FONT> slcompress *slcomp = ippp_table[slot]->slcomp;
|
|
t.vj.vjs_packets = slcomp->sls_o_compressed + slcomp->sls_o_uncompressed;
|
|
t.vj.vjs_compressed = slcomp->sls_o_compressed;
|
|
t.vj.vjs_searches = slcomp->sls_o_searches;
|
|
t.vj.vjs_misses = slcomp->sls_o_misses;
|
|
t.vj.vjs_errorin = slcomp->sls_i_error;
|
|
t.vj.vjs_tossed = slcomp->sls_i_tossed;
|
|
t.vj.vjs_uncompressedin = slcomp->sls_i_uncompressed;
|
|
t.vj.vjs_compressedin = slcomp->sls_i_compressed;
|
|
}
|
|
<FONT COLOR=#A521F7>#endif</FONT>
|
|
}
|
|
<FONT COLOR="#298C52">if</FONT>( copy_to_user(res, &t, <FONT COLOR="#298C52">sizeof</FONT>(<FONT COLOR="#298C52">struct</FONT> ppp_stats))) <FONT COLOR="#298C52">return</FONT> -EFAULT;
|
|
<FONT COLOR="#298C52">return</FONT> 0;
|
|
}
|
|
|
|
<FONT COLOR="#298C52">int</FONT>
|
|
<A HREF="#isdn_ppp_dev_ioctl">isdn_ppp_dev_ioctl</A>(<FONT COLOR="#298C52">struct</FONT> device *dev, <FONT COLOR="#298C52">struct</FONT> ifreq *ifr, <FONT COLOR="#298C52">int</FONT> cmd)
|
|
{
|
|
<FONT COLOR="#298C52">int</FONT> error=0;
|
|
<FONT COLOR="#298C52">char</FONT> *r;
|
|
<FONT COLOR="#298C52">int</FONT> len;
|
|
isdn_net_local *lp = (isdn_net_local *) dev->priv;
|
|
|
|
<FONT COLOR=#A521F7>#if</FONT> 0
|
|
printk(KERN_DEBUG <FONT COLOR="#FF0000">"ippp, dev_ioctl: cmd %#08x , %d \n"</FONT>, cmd, lp->ppp_slot);
|
|
<FONT COLOR=#A521F7>#endif</FONT>
|
|
|
|
<FONT COLOR="#298C52">if</FONT> (lp->p_encap != <A HREF="../includes/isdn.h.shtml#ISDN_NET_ENCAP_SYNCPPP">ISDN_NET_ENCAP_SYNCPPP</A>)
|
|
<FONT COLOR="#298C52">return</FONT> -EINVAL;
|
|
|
|
<FONT COLOR="#298C52">switch</FONT> (cmd) {
|
|
<FONT COLOR="#298C52">case</FONT> SIOCGPPPVER:
|
|
r = (<FONT COLOR="#298C52">char</FONT> *) ifr->ifr_ifru.ifru_data;
|
|
len = strlen(PPP_VERSION) + 1;
|
|
<FONT COLOR="#298C52">if</FONT>(copy_to_user(r, PPP_VERSION, len)) error = -EFAULT;
|
|
<FONT COLOR="#298C52">break</FONT>;
|
|
<FONT COLOR="#298C52">case</FONT> SIOCGPPPSTATS:
|
|
error = <A HREF="#isdn_ppp_dev_ioctl_stats">isdn_ppp_dev_ioctl_stats</A>(lp->ppp_slot, ifr, dev);
|
|
<FONT COLOR="#298C52">break</FONT>;
|
|
<FONT COLOR="#298C52">default</FONT>:
|
|
error = -EINVAL;
|
|
<FONT COLOR="#298C52">break</FONT>;
|
|
}
|
|
<FONT COLOR="#298C52">return</FONT> error;
|
|
}
|
|
|
|
<FONT COLOR="#298C52">static</FONT> <FONT COLOR="#298C52">int</FONT>
|
|
<A NAME="isdn_ppp_if_get_unit">isdn_ppp_if_get_unit</A>(<FONT COLOR="#298C52">char</FONT> *<A HREF="isdn_common.c.shtml#name">name</A>)
|
|
{
|
|
<FONT COLOR="#298C52">int</FONT> len,
|
|
i,
|
|
unit = 0,
|
|
deci;
|
|
|
|
len = strlen(<A HREF="isdn_common.c.shtml#name">name</A>);
|
|
|
|
<FONT COLOR="#298C52">if</FONT> (strncmp(<FONT COLOR="#FF0000">"ippp"</FONT>, <A HREF="isdn_common.c.shtml#name">name</A>, 4) || len > 8)
|
|
<FONT COLOR="#298C52">return</FONT> -1;
|
|
|
|
<FONT COLOR="#298C52">for</FONT> (i = 0, deci = 1; i < len; i++, deci *= 10) {
|
|
<FONT COLOR="#298C52">char</FONT> a = <A HREF="isdn_common.c.shtml#name">name</A>[len - i - 1];
|
|
<FONT COLOR="#298C52">if</FONT> (a >= <FONT COLOR="#FF0000">'0'</FONT> && a <= <FONT COLOR="#FF0000">'9'</FONT>)
|
|
unit += (a - <FONT COLOR="#FF0000">'0'</FONT>) * deci;
|
|
<FONT COLOR="#298C52">else</FONT>
|
|
<FONT COLOR="#298C52">break</FONT>;
|
|
}
|
|
<FONT COLOR="#298C52">if</FONT> (!i || len - i != 4)
|
|
unit = -1;
|
|
|
|
<FONT COLOR="#298C52">return</FONT> unit;
|
|
}
|
|
|
|
|
|
<FONT COLOR="#298C52">int</FONT>
|
|
<A NAME="isdn_ppp_dial_slave">isdn_ppp_dial_slave</A>(<FONT COLOR="#298C52">char</FONT> *<A HREF="isdn_common.c.shtml#name">name</A>)
|
|
{
|
|
<FONT COLOR=#A521F7>#ifdef</FONT> CONFIG_ISDN_MPP
|
|
<A HREF="../includes/isdn.h.shtml#isdn_net_dev">isdn_net_dev</A> *ndev;
|
|
isdn_net_local *lp;
|
|
<FONT COLOR="#298C52">struct</FONT> device *sdev;
|
|
|
|
<FONT COLOR="#298C52">if</FONT> (!(ndev = <A HREF="isdn_net.c.shtml#isdn_net_findif">isdn_net_findif</A>(<A HREF="isdn_common.c.shtml#name">name</A>)))
|
|
<FONT COLOR="#298C52">return</FONT> 1;
|
|
lp = ndev->local;
|
|
<FONT COLOR="#298C52">if</FONT> (!(lp->flags & <A HREF="../includes/isdn.h.shtml#ISDN_NET_CONNECTED">ISDN_NET_CONNECTED</A>))
|
|
<FONT COLOR="#298C52">return</FONT> 5;
|
|
|
|
sdev = lp->slave;
|
|
<FONT COLOR="#298C52">while</FONT> (sdev) {
|
|
isdn_net_local *mlp = (isdn_net_local *) sdev->priv;
|
|
<FONT COLOR="#298C52">if</FONT> (!(mlp->flags & <A HREF="../includes/isdn.h.shtml#ISDN_NET_CONNECTED">ISDN_NET_CONNECTED</A>))
|
|
<FONT COLOR="#298C52">break</FONT>;
|
|
sdev = mlp->slave;
|
|
}
|
|
<FONT COLOR="#298C52">if</FONT> (!sdev)
|
|
<FONT COLOR="#298C52">return</FONT> 2;
|
|
|
|
<A HREF="isdn_net.c.shtml#isdn_net_force_dial_lp">isdn_net_force_dial_lp</A>((isdn_net_local *) sdev->priv);
|
|
<FONT COLOR="#298C52">return</FONT> 0;
|
|
<FONT COLOR=#A521F7>#else</FONT>
|
|
<FONT COLOR="#298C52">return</FONT> -1;
|
|
<FONT COLOR=#A521F7>#endif</FONT>
|
|
}
|
|
|
|
<FONT COLOR="#298C52">int</FONT>
|
|
<A NAME="isdn_ppp_hangup_slave">isdn_ppp_hangup_slave</A>(<FONT COLOR="#298C52">char</FONT> *<A HREF="isdn_common.c.shtml#name">name</A>)
|
|
{
|
|
<FONT COLOR=#A521F7>#ifdef</FONT> CONFIG_ISDN_MPP
|
|
<A HREF="../includes/isdn.h.shtml#isdn_net_dev">isdn_net_dev</A> *ndev;
|
|
isdn_net_local *lp;
|
|
<FONT COLOR="#298C52">struct</FONT> device *sdev;
|
|
|
|
<FONT COLOR="#298C52">if</FONT> (!(ndev = <A HREF="isdn_net.c.shtml#isdn_net_findif">isdn_net_findif</A>(<A HREF="isdn_common.c.shtml#name">name</A>)))
|
|
<FONT COLOR="#298C52">return</FONT> 1;
|
|
lp = ndev->local;
|
|
<FONT COLOR="#298C52">if</FONT> (!(lp->flags & <A HREF="../includes/isdn.h.shtml#ISDN_NET_CONNECTED">ISDN_NET_CONNECTED</A>))
|
|
<FONT COLOR="#298C52">return</FONT> 5;
|
|
|
|
sdev = lp->slave;
|
|
<FONT COLOR="#298C52">while</FONT> (sdev) {
|
|
isdn_net_local *mlp = (isdn_net_local *) sdev->priv;
|
|
<FONT COLOR="#298C52">if</FONT> ((mlp->flags & <A HREF="../includes/isdn.h.shtml#ISDN_NET_CONNECTED">ISDN_NET_CONNECTED</A>))
|
|
<FONT COLOR="#298C52">break</FONT>;
|
|
sdev = mlp->slave;
|
|
}
|
|
<FONT COLOR="#298C52">if</FONT> (!sdev)
|
|
<FONT COLOR="#298C52">return</FONT> 2;
|
|
|
|
<A HREF="isdn_net.c.shtml#isdn_net_hangup">isdn_net_hangup</A>(sdev);
|
|
<FONT COLOR="#298C52">return</FONT> 0;
|
|
<FONT COLOR=#A521F7>#else</FONT>
|
|
<FONT COLOR="#298C52">return</FONT> -1;
|
|
<FONT COLOR=#A521F7>#endif</FONT>
|
|
}
|
|
|
|
<FONT COLOR=#0000FF>/*
|
|
* PPP compression stuff
|
|
*/</FONT>
|
|
<FONT COLOR="#298C52">static</FONT> <FONT COLOR="#298C52">struct</FONT> sk_buff *<A HREF="#isdn_ppp_decompress">isdn_ppp_decompress</A>(<FONT COLOR="#298C52">struct</FONT> sk_buff *skb,<FONT COLOR="#298C52">struct</FONT> ippp_struct *is,<FONT COLOR="#298C52">struct</FONT> ippp_struct *master,
|
|
<FONT COLOR="#298C52">int</FONT> proto)
|
|
{
|
|
<FONT COLOR=#A521F7>#ifndef</FONT> <A HREF="#CONFIG_ISDN_CCP">CONFIG_ISDN_CCP</A>
|
|
<FONT COLOR="#298C52">if</FONT>(proto == PPP_COMP || proto == <A HREF="../includes/isdn_ppp.h.shtml#PPP_LINK_COMP">PPP_LINK_COMP</A>) {
|
|
printk(KERN_ERR <FONT COLOR="#FF0000">"isdn_ppp: Ouch! Compression not included!\n"</FONT>);
|
|
dev_kfree_skb(skb);
|
|
<FONT COLOR="#298C52">return</FONT> NULL;
|
|
}
|
|
<FONT COLOR="#298C52">return</FONT> skb;
|
|
<FONT COLOR=#A521F7>#else</FONT>
|
|
<FONT COLOR="#298C52">void</FONT> *stat = NULL;
|
|
<FONT COLOR="#298C52">struct</FONT> isdn_ppp_compressor *ipc = NULL;
|
|
<FONT COLOR="#298C52">struct</FONT> sk_buff *skb_out;
|
|
<FONT COLOR="#298C52">int</FONT> len;
|
|
|
|
<FONT COLOR="#298C52">if</FONT>(!master) {
|
|
<FONT COLOR=#0000FF>/*
|
|
* single link decompression
|
|
*/</FONT>
|
|
<FONT COLOR="#298C52">if</FONT>(!is->link_decompressor) {
|
|
printk(KERN_ERR <FONT COLOR="#FF0000">"ippp: no link decompressor defined!\n"</FONT>);
|
|
dev_kfree_skb(skb);
|
|
<FONT COLOR="#298C52">return</FONT> NULL;
|
|
}
|
|
<FONT COLOR="#298C52">if</FONT>(!is->link_decomp_stat) {
|
|
printk(KERN_DEBUG <FONT COLOR="#FF0000">"ippp: no link decompressor data allocated\n"</FONT>);
|
|
dev_kfree_skb(skb);
|
|
<FONT COLOR="#298C52">return</FONT> NULL;
|
|
}
|
|
stat = is->link_decomp_stat;
|
|
ipc = is->link_decompressor;
|
|
}
|
|
<FONT COLOR="#298C52">else</FONT> {
|
|
<FONT COLOR=#0000FF>/*
|
|
* 'normal' or bundle-compression
|
|
*/</FONT>
|
|
<FONT COLOR="#298C52">if</FONT>(!master->decompressor) {
|
|
printk(KERN_ERR <FONT COLOR="#FF0000">"ippp: no decompressor defined!\n"</FONT>);
|
|
dev_kfree_skb(skb);
|
|
<FONT COLOR="#298C52">return</FONT> NULL;
|
|
}
|
|
<FONT COLOR="#298C52">if</FONT>(!master->decomp_stat) {
|
|
printk(KERN_DEBUG <FONT COLOR="#FF0000">"ippp: no decompressor data allocated\n"</FONT>);
|
|
dev_kfree_skb(skb);
|
|
<FONT COLOR="#298C52">return</FONT> NULL;
|
|
}
|
|
stat = master->decomp_stat;
|
|
ipc = master->decompressor;
|
|
}
|
|
|
|
printk(KERN_DEBUG <FONT COLOR="#FF0000">"ippp: Decompress valid!\n"</FONT>);
|
|
|
|
<FONT COLOR="#298C52">if</FONT>((master && proto == PPP_COMP) || (!master && proto == <A HREF="../includes/isdn_ppp.h.shtml#PPP_LINK_COMP">PPP_LINK_COMP</A>) ) {
|
|
<FONT COLOR=#0000FF>/* !!!HACK,HACK,HACK!!! 2048 is only assumed */</FONT>
|
|
skb_out = dev_alloc_skb(2048);
|
|
len = ipc->decompress(stat,skb,skb_out);
|
|
dev_kfree_skb(skb);
|
|
<FONT COLOR="#298C52">if</FONT>(len <= 0) {
|
|
<FONT COLOR="#298C52">return</FONT> NULL;
|
|
}
|
|
<FONT COLOR="#298C52">return</FONT> skb_out;
|
|
}
|
|
<FONT COLOR="#298C52">else</FONT> {
|
|
printk(KERN_DEBUG <FONT COLOR="#FF0000">"isdn_ppp: [%d] Calling incomp with this frame!\n"</FONT>,is->unit);
|
|
ipc->incomp(stat,skb,proto);
|
|
<FONT COLOR="#298C52">return</FONT> skb;
|
|
}
|
|
<FONT COLOR=#A521F7>#endif</FONT>
|
|
}
|
|
|
|
<FONT COLOR=#0000FF>/*
|
|
* compress a frame
|
|
* type=0: normal/bundle compression
|
|
* =1: link compression
|
|
* returns original skb if we haven't compressed the frame
|
|
* and a new skb pointer if we've done it
|
|
*/</FONT>
|
|
<FONT COLOR="#298C52">static</FONT> <FONT COLOR="#298C52">struct</FONT> sk_buff *<A HREF="#isdn_ppp_compress">isdn_ppp_compress</A>(<FONT COLOR="#298C52">struct</FONT> sk_buff *skb_in,<FONT COLOR="#298C52">int</FONT> *proto,
|
|
<FONT COLOR="#298C52">struct</FONT> ippp_struct *is,<FONT COLOR="#298C52">struct</FONT> ippp_struct *master,<FONT COLOR="#298C52">int</FONT> type)
|
|
{
|
|
<FONT COLOR="#298C52">int</FONT> ret;
|
|
<FONT COLOR="#298C52">int</FONT> new_proto;
|
|
<FONT COLOR="#298C52">struct</FONT> isdn_ppp_compressor *compressor;
|
|
<FONT COLOR="#298C52">void</FONT> *stat;
|
|
<FONT COLOR="#298C52">struct</FONT> sk_buff *skb_out;
|
|
|
|
<FONT COLOR=#A521F7>#ifdef</FONT> <A HREF="#CONFIG_ISDN_CCP">CONFIG_ISDN_CCP</A>
|
|
<FONT COLOR=#0000FF>/* we do not compress control protocols */</FONT>
|
|
<FONT COLOR="#298C52">if</FONT>(*proto < 0 || *proto > 0x3fff) {
|
|
<FONT COLOR=#A521F7>#else</FONT>
|
|
{
|
|
<FONT COLOR=#A521F7>#endif</FONT>
|
|
<FONT COLOR="#298C52">return</FONT> skb_in;
|
|
}
|
|
|
|
<FONT COLOR="#298C52">if</FONT>(type) { <FONT COLOR=#0000FF>/* type=1 => Link compression */</FONT>
|
|
<FONT COLOR=#A521F7>#if</FONT> 0
|
|
compressor = is->link_compressor;
|
|
stat = is->link_comp_stat;
|
|
new_proto = <A HREF="../includes/isdn_ppp.h.shtml#PPP_LINK_COMP">PPP_LINK_COMP</A>;
|
|
<FONT COLOR=#A521F7>#else</FONT>
|
|
<FONT COLOR="#298C52">return</FONT> skb_in;
|
|
<FONT COLOR=#A521F7>#endif</FONT>
|
|
}
|
|
<FONT COLOR="#298C52">else</FONT> {
|
|
<FONT COLOR="#298C52">if</FONT>(!master) {
|
|
compressor = is->compressor;
|
|
stat = is->comp_stat;
|
|
}
|
|
<FONT COLOR="#298C52">else</FONT> {
|
|
compressor = master->compressor;
|
|
stat = master->comp_stat;
|
|
}
|
|
new_proto = PPP_COMP;
|
|
}
|
|
|
|
<FONT COLOR="#298C52">if</FONT>(!compressor) {
|
|
printk(KERN_ERR <FONT COLOR="#FF0000">"isdn_ppp: No compressor set!\n"</FONT>);
|
|
<FONT COLOR="#298C52">return</FONT> skb_in;
|
|
}
|
|
<FONT COLOR="#298C52">if</FONT>(!stat) {
|
|
printk(KERN_ERR <FONT COLOR="#FF0000">"isdn_ppp: Compressor not initialized?\n"</FONT>);
|
|
<FONT COLOR="#298C52">return</FONT> skb_in;
|
|
}
|
|
|
|
skb_out = dev_alloc_skb(skb_in->len+32); <FONT COLOR=#0000FF>/* 32 little additonal space */</FONT>
|
|
<FONT COLOR="#298C52">if</FONT>(!skb_out)
|
|
<FONT COLOR="#298C52">return</FONT> skb_in;
|
|
|
|
ret = (compressor->compress)(stat,skb_in,skb_out,*proto);
|
|
<FONT COLOR="#298C52">if</FONT>(!ret) {
|
|
dev_kfree_skb(skb_out);
|
|
<FONT COLOR="#298C52">return</FONT> skb_in;
|
|
}
|
|
|
|
dev_kfree_skb(skb_in);
|
|
*proto = new_proto;
|
|
<FONT COLOR="#298C52">return</FONT> skb_out;
|
|
}
|
|
|
|
<FONT COLOR=#0000FF>/*
|
|
* we received a CCP frame ..
|
|
* not a clean solution, but we MUST handle a few cases in the kernel
|
|
*/</FONT>
|
|
<FONT COLOR="#298C52">static</FONT> <FONT COLOR="#298C52">void</FONT> <A HREF="#isdn_ppp_receive_ccp">isdn_ppp_receive_ccp</A>(<A HREF="../includes/isdn.h.shtml#isdn_net_dev">isdn_net_dev</A> *net_dev, isdn_net_local *lp,
|
|
<FONT COLOR="#298C52">struct</FONT> sk_buff *skb,<FONT COLOR="#298C52">int</FONT> proto)
|
|
{
|
|
<FONT COLOR="#298C52">struct</FONT> ippp_struct *is = ippp_table[lp->ppp_slot];
|
|
<FONT COLOR="#298C52">struct</FONT> ippp_struct *mis;
|
|
|
|
<FONT COLOR="#298C52">if</FONT>(lp->master)
|
|
mis = ippp_table[((isdn_net_local *) (lp->master->priv))->ppp_slot];
|
|
<FONT COLOR="#298C52">else</FONT>
|
|
mis = is;
|
|
|
|
<FONT COLOR="#298C52">switch</FONT>(skb->data[0]) {
|
|
<FONT COLOR="#298C52">case</FONT> CCP_CONFREQ:
|
|
<FONT COLOR="#298C52">case</FONT> CCP_TERMREQ:
|
|
<FONT COLOR="#298C52">case</FONT> CCP_TERMACK:
|
|
<FONT COLOR="#298C52">if</FONT>(is->debug & 0x10)
|
|
printk(KERN_DEBUG <FONT COLOR="#FF0000">"Disable (de)compression here!\n"</FONT>);
|
|
<FONT COLOR="#298C52">if</FONT>(proto == PPP_CCP)
|
|
mis->compflags &= ~(<A HREF="../includes/isdn_ppp.h.shtml#SC_DECOMP_ON">SC_DECOMP_ON</A>|<A HREF="../includes/isdn_ppp.h.shtml#SC_COMP_ON">SC_COMP_ON</A>);
|
|
<FONT COLOR="#298C52">else</FONT>
|
|
is->compflags &= ~(<A HREF="../includes/isdn_ppp.h.shtml#SC_LINK_DECOMP_ON">SC_LINK_DECOMP_ON</A>|<A HREF="../includes/isdn_ppp.h.shtml#SC_LINK_COMP_ON">SC_LINK_COMP_ON</A>);
|
|
<FONT COLOR="#298C52">break</FONT>;
|
|
<FONT COLOR="#298C52">case</FONT> CCP_CONFACK:
|
|
<FONT COLOR=#0000FF>/* if we RECEIVE an ackowledge we enable the decompressor */</FONT>
|
|
<FONT COLOR="#298C52">if</FONT>(is->debug & 0x10)
|
|
printk(KERN_DEBUG <FONT COLOR="#FF0000">"Enable decompression here!\n"</FONT>);
|
|
<FONT COLOR="#298C52">if</FONT>(proto == PPP_CCP)
|
|
mis->compflags |= <A HREF="../includes/isdn_ppp.h.shtml#SC_DECOMP_ON">SC_DECOMP_ON</A>;
|
|
<FONT COLOR="#298C52">else</FONT>
|
|
is->compflags |= <A HREF="../includes/isdn_ppp.h.shtml#SC_LINK_DECOMP_ON">SC_LINK_DECOMP_ON</A>;
|
|
<FONT COLOR="#298C52">break</FONT>;
|
|
<FONT COLOR="#298C52">case</FONT> CCP_RESETACK:
|
|
<FONT COLOR="#298C52">if</FONT>(is->debug & 0x10)
|
|
printk(KERN_DEBUG <FONT COLOR="#FF0000">"Reset decompression state here!\n"</FONT>);
|
|
<FONT COLOR="#298C52">if</FONT>(proto == PPP_CCP) {
|
|
<FONT COLOR="#298C52">if</FONT>(mis->decompressor && mis->decomp_stat)
|
|
mis->decompressor->reset(mis->decomp_stat);
|
|
mis->compflags &= ~<A HREF="../includes/isdn_ppp.h.shtml#SC_DECOMP_DISCARD">SC_DECOMP_DISCARD</A>;
|
|
}
|
|
<FONT COLOR="#298C52">else</FONT> {
|
|
<FONT COLOR="#298C52">if</FONT>(is->link_decompressor && is->link_decomp_stat)
|
|
is->link_decompressor->reset(is->link_decomp_stat);
|
|
is->compflags &= ~<A HREF="../includes/isdn_ppp.h.shtml#SC_LINK_DECOMP_DISCARD">SC_LINK_DECOMP_DISCARD</A>;
|
|
}
|
|
<FONT COLOR="#298C52">break</FONT>;
|
|
}
|
|
}
|
|
|
|
<FONT COLOR=#0000FF>/*
|
|
* Daemon sends a CCP frame ...
|
|
*/</FONT>
|
|
<FONT COLOR="#298C52">static</FONT> <FONT COLOR="#298C52">void</FONT> <A HREF="#isdn_ppp_send_ccp">isdn_ppp_send_ccp</A>(<A HREF="../includes/isdn.h.shtml#isdn_net_dev">isdn_net_dev</A> *net_dev, isdn_net_local *lp, <FONT COLOR="#298C52">struct</FONT> sk_buff *skb)
|
|
{
|
|
<FONT COLOR="#298C52">struct</FONT> ippp_struct *mis,*is = ippp_table[lp->ppp_slot];
|
|
<FONT COLOR="#298C52">int</FONT> proto;
|
|
|
|
<FONT COLOR="#298C52">if</FONT>(!skb || skb->len < 3)
|
|
<FONT COLOR="#298C52">return</FONT>;
|
|
proto = ((<FONT COLOR="#298C52">int</FONT>)skb->data[0]<<8)+skb->data[1];
|
|
<FONT COLOR="#298C52">if</FONT>(proto != PPP_CCP && proto != <A HREF="../includes/isdn_ppp.h.shtml#PPP_LINK_CCP">PPP_LINK_CCP</A>)
|
|
<FONT COLOR="#298C52">return</FONT>;
|
|
|
|
<FONT COLOR="#298C52">if</FONT>(lp->master)
|
|
mis = ippp_table[((isdn_net_local *) (lp->master->priv))->ppp_slot];
|
|
<FONT COLOR="#298C52">else</FONT>
|
|
mis = is;
|
|
|
|
<FONT COLOR="#298C52">if</FONT>(mis != is)
|
|
printk(KERN_DEBUG <FONT COLOR="#FF0000">"isdn_ppp: Ouch! Master CCP sends on slave slot!\n"</FONT>);
|
|
|
|
<FONT COLOR="#298C52">switch</FONT>(skb->data[2]) {
|
|
<FONT COLOR="#298C52">case</FONT> CCP_CONFREQ:
|
|
<FONT COLOR="#298C52">case</FONT> CCP_TERMREQ:
|
|
<FONT COLOR="#298C52">case</FONT> CCP_TERMACK:
|
|
<FONT COLOR="#298C52">if</FONT>(is->debug & 0x10)
|
|
printk(KERN_DEBUG <FONT COLOR="#FF0000">"Disable (de)compression here!\n"</FONT>);
|
|
<FONT COLOR="#298C52">if</FONT>(proto == PPP_CCP)
|
|
is->compflags &= ~(<A HREF="../includes/isdn_ppp.h.shtml#SC_DECOMP_ON">SC_DECOMP_ON</A>|<A HREF="../includes/isdn_ppp.h.shtml#SC_COMP_ON">SC_COMP_ON</A>);
|
|
<FONT COLOR="#298C52">else</FONT>
|
|
is->compflags &= ~(<A HREF="../includes/isdn_ppp.h.shtml#SC_LINK_DECOMP_ON">SC_LINK_DECOMP_ON</A>|<A HREF="../includes/isdn_ppp.h.shtml#SC_LINK_COMP_ON">SC_LINK_COMP_ON</A>);
|
|
<FONT COLOR="#298C52">break</FONT>;
|
|
<FONT COLOR="#298C52">case</FONT> CCP_CONFACK:
|
|
<FONT COLOR=#0000FF>/* if we SEND an ackowledge we can/must enable the compressor */</FONT>
|
|
<FONT COLOR="#298C52">if</FONT>(is->debug & 0x10)
|
|
printk(KERN_DEBUG <FONT COLOR="#FF0000">"Enable compression here!\n"</FONT>);
|
|
<FONT COLOR="#298C52">if</FONT>(proto == PPP_CCP)
|
|
is->compflags |= <A HREF="../includes/isdn_ppp.h.shtml#SC_COMP_ON">SC_COMP_ON</A>;
|
|
<FONT COLOR="#298C52">else</FONT>
|
|
is->compflags |= <A HREF="../includes/isdn_ppp.h.shtml#SC_LINK_COMP_ON">SC_LINK_COMP_ON</A>;
|
|
<FONT COLOR="#298C52">break</FONT>;
|
|
<FONT COLOR="#298C52">case</FONT> CCP_RESETACK:
|
|
<FONT COLOR=#0000FF>/* If we send a ACK we should reset our compressor */</FONT>
|
|
<FONT COLOR="#298C52">if</FONT>(is->debug & 0x10)
|
|
printk(KERN_DEBUG <FONT COLOR="#FF0000">"Reset decompression state here!\n"</FONT>);
|
|
<FONT COLOR="#298C52">if</FONT>(proto == PPP_CCP) {
|
|
<FONT COLOR=#0000FF>/* link to master? */</FONT>
|
|
<FONT COLOR="#298C52">if</FONT>(is->compressor && is->comp_stat)
|
|
is->compressor->reset(is->comp_stat);
|
|
is->compflags &= ~<A HREF="../includes/isdn_ppp.h.shtml#SC_COMP_DISCARD">SC_COMP_DISCARD</A>;
|
|
}
|
|
<FONT COLOR="#298C52">else</FONT> {
|
|
<FONT COLOR="#298C52">if</FONT>(is->link_compressor && is->link_comp_stat)
|
|
is->link_compressor->reset(is->link_comp_stat);
|
|
is->compflags &= ~<A HREF="../includes/isdn_ppp.h.shtml#SC_LINK_COMP_DISCARD">SC_LINK_COMP_DISCARD</A>;
|
|
}
|
|
<FONT COLOR="#298C52">break</FONT>;
|
|
}
|
|
}
|
|
|
|
|
|
<FONT COLOR="#298C52">int</FONT> <A HREF="#isdn_ppp_register_compressor">isdn_ppp_register_compressor</A>(<FONT COLOR="#298C52">struct</FONT> isdn_ppp_compressor *ipc)
|
|
{
|
|
ipc->next = ipc_head;
|
|
ipc->prev = NULL;
|
|
<FONT COLOR="#298C52">if</FONT>(ipc_head) {
|
|
ipc_head->prev = ipc;
|
|
}
|
|
ipc_head = ipc;
|
|
<FONT COLOR="#298C52">return</FONT> 0;
|
|
}
|
|
|
|
<FONT COLOR="#298C52">int</FONT> <A HREF="#isdn_ppp_unregister_compressor">isdn_ppp_unregister_compressor</A>(<FONT COLOR="#298C52">struct</FONT> isdn_ppp_compressor *ipc)
|
|
{
|
|
<FONT COLOR="#298C52">if</FONT>(ipc->prev)
|
|
ipc->prev->next = ipc->next;
|
|
<FONT COLOR="#298C52">else</FONT>
|
|
ipc_head = ipc->next;
|
|
<FONT COLOR="#298C52">if</FONT>(ipc->next)
|
|
ipc->next->prev = ipc->prev;
|
|
ipc->prev = ipc->next = NULL;
|
|
<FONT COLOR="#298C52">return</FONT> 0;
|
|
}
|
|
|
|
<FONT COLOR="#298C52">static</FONT> <FONT COLOR="#298C52">int</FONT> <A HREF="#isdn_ppp_set_compressor">isdn_ppp_set_compressor</A>(<FONT COLOR="#298C52">struct</FONT> ippp_struct *is, <FONT COLOR="#298C52">struct</FONT> isdn_ppp_comp_data *data)
|
|
{
|
|
<FONT COLOR="#298C52">struct</FONT> isdn_ppp_compressor *ipc = ipc_head;
|
|
<FONT COLOR="#298C52">int</FONT> ret;
|
|
<FONT COLOR="#298C52">void</FONT> *stat;
|
|
<FONT COLOR="#298C52">int</FONT> num = data->num;
|
|
|
|
<FONT COLOR="#298C52">if</FONT>(is->debug & 0x10)
|
|
printk(KERN_DEBUG <FONT COLOR="#FF0000">"[%d] Set %s type %d\n"</FONT>,is->unit,
|
|
(data->flags&<A HREF="../includes/isdn_ppp.h.shtml#IPPP_COMP_FLAG_XMIT">IPPP_COMP_FLAG_XMIT</A>)?<FONT COLOR="#FF0000">"compressor"</FONT>:<FONT COLOR="#FF0000">"decompressor"</FONT>,num);
|
|
|
|
<FONT COLOR="#298C52">while</FONT>(ipc) {
|
|
<FONT COLOR="#298C52">if</FONT>(ipc->num == num) {
|
|
stat = ipc->alloc(data);
|
|
<FONT COLOR="#298C52">if</FONT>(stat) {
|
|
ret = ipc->init(stat,data,is->unit,0);
|
|
<FONT COLOR="#298C52">if</FONT>(!ret) {
|
|
printk(KERN_ERR <FONT COLOR="#FF0000">"Can't init (de)compression!\n"</FONT>);
|
|
ipc->free(stat);
|
|
stat = NULL;
|
|
<FONT COLOR="#298C52">break</FONT>;
|
|
}
|
|
}
|
|
<FONT COLOR="#298C52">else</FONT> {
|
|
printk(KERN_ERR <FONT COLOR="#FF0000">"Can't alloc (de)compression!\n"</FONT>);
|
|
<FONT COLOR="#298C52">break</FONT>;
|
|
}
|
|
|
|
<FONT COLOR="#298C52">if</FONT>(data->flags & <A HREF="../includes/isdn_ppp.h.shtml#IPPP_COMP_FLAG_XMIT">IPPP_COMP_FLAG_XMIT</A>) {
|
|
<FONT COLOR="#298C52">if</FONT>(data->flags & <A HREF="../includes/isdn_ppp.h.shtml#IPPP_COMP_FLAG_LINK">IPPP_COMP_FLAG_LINK</A>) {
|
|
<FONT COLOR="#298C52">if</FONT>(is->link_comp_stat)
|
|
is->link_compressor->free(is->link_comp_stat);
|
|
is->link_comp_stat = stat;
|
|
is->link_compressor = ipc;
|
|
}
|
|
<FONT COLOR="#298C52">else</FONT> {
|
|
<FONT COLOR="#298C52">if</FONT>(is->comp_stat)
|
|
is->compressor->free(is->comp_stat);
|
|
is->comp_stat = stat;
|
|
is->compressor = ipc;
|
|
}
|
|
}
|
|
<FONT COLOR="#298C52">else</FONT> {
|
|
<FONT COLOR="#298C52">if</FONT>(data->flags & <A HREF="../includes/isdn_ppp.h.shtml#IPPP_COMP_FLAG_LINK">IPPP_COMP_FLAG_LINK</A>) {
|
|
<FONT COLOR="#298C52">if</FONT>(is->link_decomp_stat)
|
|
is->link_decompressor->free(is->link_decomp_stat);
|
|
is->link_decomp_stat = stat;
|
|
is->link_decompressor = ipc;
|
|
}
|
|
<FONT COLOR="#298C52">else</FONT> {
|
|
<FONT COLOR="#298C52">if</FONT>(is->decomp_stat)
|
|
is->decompressor->free(is->decomp_stat);
|
|
is->decomp_stat = stat;
|
|
is->decompressor = ipc;
|
|
}
|
|
}
|
|
<FONT COLOR="#298C52">return</FONT> 0;
|
|
}
|
|
ipc = ipc->next;
|
|
}
|
|
<FONT COLOR="#298C52">return</FONT> -EINVAL;
|
|
}
|
|
|
|
|
|
</BODY>
|
|
|
|
</HTML>
|