isdn4linux-web/workshop/linklevel/isdn_ppp.c.shtml

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&lt;-&gt;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 &gt;= 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> &lt;linux/config.h&gt;
<FONT COLOR=#A521F7>#define</FONT> <A HREF="isdn_audio.c.shtml#__NO_VERSION__">__NO_VERSION__</A>
<FONT COLOR=#A521F7>#include</FONT> &lt;linux/module.h&gt;
<FONT COLOR=#A521F7>#include</FONT> &lt;linux/version.h&gt;
<FONT COLOR=#A521F7>#include</FONT> &lt;linux/poll.h&gt;
<FONT COLOR=#A521F7>#include</FONT> &lt;linux/isdn.h&gt;
<FONT COLOR=#A521F7>#include</FONT> &lt;linux/ppp-comp.h&gt;
<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 &lt; maxlen)
maxlen = len;
<FONT COLOR="#298C52">for</FONT> (i = 0, cnt = 0; cnt &lt; maxlen; i++) {
<FONT COLOR="#298C52">for</FONT> (j = 0; j &lt; 16 &amp;&amp; cnt &lt; 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 &lt;=&gt; 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-&gt;ppp_slot &lt; 0 || lp-&gt;ppp_slot &gt; <A HREF="../includes/isdn.h.shtml#ISDN_MAX_CHANNELS">ISDN_MAX_CHANNELS</A>)
<FONT COLOR="#298C52">return</FONT> 0;
is = ippp_table[lp-&gt;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-&gt;master)
master_lp = (isdn_net_local *) lp-&gt;master-&gt;priv;
lp-&gt;last-&gt;next = lp-&gt;next;
lp-&gt;next-&gt;last = lp-&gt;last;
<FONT COLOR="#298C52">if</FONT> (master_lp-&gt;netdev-&gt;queue == lp) {
master_lp-&gt;netdev-&gt;queue = lp-&gt;next;
<FONT COLOR="#298C52">if</FONT> (lp-&gt;next == lp) { <FONT COLOR=#0000FF>/* last link in queue? */</FONT>
master_lp-&gt;netdev-&gt;ib.bundled = 0;
<A HREF="#isdn_ppp_free_mpqueue">isdn_ppp_free_mpqueue</A>(master_lp-&gt;netdev);
<A HREF="#isdn_ppp_free_sqqueue">isdn_ppp_free_sqqueue</A>(master_lp-&gt;netdev);
}
}
lp-&gt;next = lp-&gt;last = lp; <FONT COLOR=#0000FF>/* (re)set own pointers */</FONT>
<FONT COLOR=#A521F7>#endif</FONT>
<FONT COLOR="#298C52">if</FONT> ((is-&gt;state &amp; <A HREF="isdn_ppp.h.shtml#IPPP_CONNECT">IPPP_CONNECT</A>))
<A HREF="#isdn_ppp_closewait">isdn_ppp_closewait</A>(lp-&gt;ppp_slot); <FONT COLOR=#0000FF>/* force wakeup on ippp device */</FONT>
<FONT COLOR="#298C52">else</FONT> <FONT COLOR="#298C52">if</FONT> (is-&gt;state &amp; <A HREF="isdn_ppp.h.shtml#IPPP_ASSIGNED">IPPP_ASSIGNED</A>)
is-&gt;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-&gt;debug &amp; 0x1)
printk(KERN_DEBUG <FONT COLOR="#FF0000">"isdn_ppp_free %d %lx %lx\n"</FONT>, lp-&gt;ppp_slot, (<FONT COLOR="#298C52">long</FONT>) lp, (<FONT COLOR="#298C52">long</FONT>) is-&gt;lp);
is-&gt;lp = NULL; <FONT COLOR=#0000FF>/* link is down .. set lp to NULL */</FONT>
<FONT COLOR=#A521F7>#ifdef</FONT> ISDN_SYNCPPP_READDRESS
is-&gt;old_pa_addr = 0x0;
is-&gt;old_pa_dstaddr = 0x0;
<FONT COLOR=#A521F7>#endif</FONT>
lp-&gt;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 &lt;=&gt; 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-&gt;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-&gt;pppbind &lt; 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-&gt;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-&gt;local;
<FONT COLOR="#298C52">if</FONT> (lp-&gt;pppbind &gt;= 0)
exclusive[lp-&gt;pppbind] = 1;
net_dev = net_dev-&gt;next;
}
<FONT COLOR=#0000FF>/*
* search a free device / slot
*/</FONT>
<FONT COLOR="#298C52">for</FONT> (i = 0; i &lt; <A HREF="../includes/isdn.h.shtml#ISDN_MAX_CHANNELS">ISDN_MAX_CHANNELS</A>; i++) {
<FONT COLOR="#298C52">if</FONT> (ippp_table[i]-&gt;state == <A HREF="isdn_ppp.h.shtml#IPPP_OPEN">IPPP_OPEN</A> &amp;&amp; !exclusive[ippp_table[i]-&gt;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 &lt; <A HREF="../includes/isdn.h.shtml#ISDN_MAX_CHANNELS">ISDN_MAX_CHANNELS</A>; i++)
<FONT COLOR="#298C52">if</FONT> (ippp_table[i]-&gt;minor == lp-&gt;pppbind &amp;&amp; ippp_table[i]-&gt;state == <A HREF="isdn_ppp.h.shtml#IPPP_OPEN">IPPP_OPEN</A>)
<FONT COLOR="#298C52">break</FONT>;
}
<FONT COLOR="#298C52">if</FONT> (i &gt;= <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-&gt;<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 &lt; 0) {
printk(KERN_ERR <FONT COLOR="#FF0000">"isdn_ppp_bind: illegal interface name %s.\n"</FONT>, lp-&gt;<A HREF="isdn_common.c.shtml#name">name</A>);
<FONT COLOR="#298C52">return</FONT> -1;
}
lp-&gt;ppp_slot = i;
is = ippp_table[i];
is-&gt;lp = lp;
is-&gt;unit = unit;
is-&gt;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-&gt;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-&gt;ppp_slot &lt; 0 || lp-&gt;ppp_slot &gt;= <A HREF="../includes/isdn.h.shtml#ISDN_MAX_CHANNELS">ISDN_MAX_CHANNELS</A>)
<FONT COLOR="#298C52">return</FONT>;
ippp_table[lp-&gt;ppp_slot]-&gt;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-&gt;ppp_slot]-&gt;wq)
wake_up_interruptible(&amp;ippp_table[lp-&gt;ppp_slot]-&gt;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 &lt; 0 || slot &gt;= <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-&gt;state &amp;&amp; is-&gt;wq)
wake_up_interruptible(&amp;is-&gt;wq);
is-&gt;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 &lt; <A HREF="../includes/isdn.h.shtml#ISDN_MAX_CHANNELS">ISDN_MAX_CHANNELS</A>; i++) {
<FONT COLOR="#298C52">if</FONT> (!ippp_table[i]-&gt;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 &lt; 0 || min &gt; <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 &lt; 0) {
<FONT COLOR="#298C52">return</FONT> -EBUSY;
}
is = file-&gt;private_data = ippp_table[slot];
<FONT COLOR=#A521F7>#if</FONT> 0
<FONT COLOR="#298C52">if</FONT> (is-&gt;debug &amp; 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-&gt;state);
<FONT COLOR=#0000FF>/* compression stuff */</FONT>
is-&gt;link_compressor = is-&gt;compressor = NULL;
is-&gt;link_decompressor = is-&gt;decompressor = NULL;
is-&gt;link_comp_stat = is-&gt;comp_stat = NULL;
is-&gt;link_decomp_stat = is-&gt;decomp_stat = NULL;
is-&gt;compflags = 0;
is-&gt;lp = NULL;
is-&gt;mp_seqno = 0; <FONT COLOR=#0000FF>/* MP sequence number */</FONT>
is-&gt;pppcfg = 0; <FONT COLOR=#0000FF>/* ppp configuration */</FONT>
is-&gt;mpppcfg = 0; <FONT COLOR=#0000FF>/* mppp configuration */</FONT>
is-&gt;range = 0x1000000; <FONT COLOR=#0000FF>/* MP: 24 bit range */</FONT>
is-&gt;last_link_seqno = -1; <FONT COLOR=#0000FF>/* MP: maybe set to Bundle-MIN, when joining a bundle ?? */</FONT>
is-&gt;unit = -1; <FONT COLOR=#0000FF>/* set, when we have our interface */</FONT>
is-&gt;mru = 1524; <FONT COLOR=#0000FF>/* MRU, default 1524 */</FONT>
is-&gt;maxcid = 16; <FONT COLOR=#0000FF>/* VJ: maxcid */</FONT>
is-&gt;tk = current;
is-&gt;wq = NULL; <FONT COLOR=#0000FF>/* read() wait queue */</FONT>
is-&gt;first = is-&gt;rq + <A HREF="../includes/isdn_ppp.h.shtml#NUM_RCV_BUFFS">NUM_RCV_BUFFS</A> - 1; <FONT COLOR=#0000FF>/* receive queue */</FONT>
is-&gt;last = is-&gt;rq;
is-&gt;minor = min;
<FONT COLOR=#A521F7>#ifdef</FONT> CONFIG_ISDN_PPP_VJ
<FONT COLOR=#0000FF>/*
* VJ header compression init
*/</FONT>
is-&gt;slcomp = slhc_init(16, 16); <FONT COLOR=#0000FF>/* not necessary for 2. link in bundle */</FONT>
<FONT COLOR=#A521F7>#endif</FONT>
is-&gt;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 &lt; 0 || min &gt;= <A HREF="../includes/isdn.h.shtml#ISDN_MAX_CHANNELS">ISDN_MAX_CHANNELS</A>)
<FONT COLOR="#298C52">return</FONT>;
is = file-&gt;private_data;
<FONT COLOR="#298C52">if</FONT> (is-&gt;debug &amp; 0x1)
printk(KERN_DEBUG <FONT COLOR="#FF0000">"ippp: release, minor: %d %lx\n"</FONT>, min, (<FONT COLOR="#298C52">long</FONT>) is-&gt;lp);
<FONT COLOR="#298C52">if</FONT> (is-&gt;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-&gt;lp-&gt;netdev;
is-&gt;state &amp;= ~<A HREF="isdn_ppp.h.shtml#IPPP_CONNECT">IPPP_CONNECT</A>; <FONT COLOR=#0000FF>/* -&gt; effect: no call of wakeup */</FONT>
<FONT COLOR=#0000FF>/*
* isdn_net_hangup() calls isdn_ppp_free()
* isdn_ppp_free() sets is-&gt;lp to NULL and lp-&gt;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>(&amp;p-&gt;dev);
}
<FONT COLOR="#298C52">for</FONT> (i = 0; i &lt; <A HREF="../includes/isdn_ppp.h.shtml#NUM_RCV_BUFFS">NUM_RCV_BUFFS</A>; i++) {
<FONT COLOR="#298C52">if</FONT> (is-&gt;rq[i].buf) {
kfree(is-&gt;rq[i].buf);
is-&gt;rq[i].buf = NULL;
}
}
is-&gt;first = is-&gt;rq + <A HREF="../includes/isdn_ppp.h.shtml#NUM_RCV_BUFFS">NUM_RCV_BUFFS</A> - 1; <FONT COLOR=#0000FF>/* receive queue */</FONT>
is-&gt;last = is-&gt;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-&gt;slcomp);
is-&gt;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-&gt;comp_stat)
is-&gt;compressor-&gt;free(is-&gt;comp_stat);
<FONT COLOR="#298C52">if</FONT>(is-&gt;link_comp_stat)
is-&gt;link_compressor-&gt;free(is-&gt;link_comp_stat);
<FONT COLOR="#298C52">if</FONT>(is-&gt;link_decomp_stat)
is-&gt;link_decompressor-&gt;free(is-&gt;link_decomp_stat);
<FONT COLOR="#298C52">if</FONT>(is-&gt;decomp_stat)
is-&gt;decompressor-&gt;free(is-&gt;decomp_stat);
is-&gt;compressor = is-&gt;link_compressor = NULL;
is-&gt;decompressor = is-&gt;link_decompressor = NULL;
is-&gt;comp_stat = is-&gt;link_comp_stat = NULL;
is-&gt;decomp_stat = is-&gt;link_decomp_stat = NULL;
<FONT COLOR=#0000FF>/* this slot is ready for new connections */</FONT>
is-&gt;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 &lt;= 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 &lt;= 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-&gt;private_data;
lp = is-&gt;lp;
<FONT COLOR="#298C52">if</FONT> (is-&gt;debug &amp; 0x1)
printk(KERN_DEBUG <FONT COLOR="#FF0000">"isdn_ppp_ioctl: minor: %d cmd: %x state: %x\n"</FONT>, min, cmd, is-&gt;state);
<FONT COLOR="#298C52">if</FONT> (!(is-&gt;state &amp; <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-&gt;state &amp; <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, &amp;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-&gt;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, &amp;is-&gt;unit, <FONT COLOR="#298C52">sizeof</FONT>(is-&gt;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-&gt;<A HREF="isdn_common.c.shtml#name">name</A>,strlen(lp-&gt;<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, &amp;is-&gt;mpppcfg, <FONT COLOR="#298C52">sizeof</FONT>(is-&gt;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, &amp;val, <FONT COLOR="#298C52">sizeof</FONT>(val) )))
<FONT COLOR="#298C52">return</FONT> r;
is-&gt;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, &amp;is-&gt;pppcfg,<FONT COLOR="#298C52">sizeof</FONT>(is-&gt;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, &amp;val, <FONT COLOR="#298C52">sizeof</FONT>(val) ))) {
<FONT COLOR="#298C52">return</FONT> r;
}
<FONT COLOR="#298C52">if</FONT> (val &amp; SC_ENABLE_IP &amp;&amp; !(is-&gt;pppcfg &amp; SC_ENABLE_IP) &amp;&amp; (is-&gt;state &amp; <A HREF="isdn_ppp.h.shtml#IPPP_CONNECT">IPPP_CONNECT</A>)) {
<FONT COLOR="#298C52">if</FONT> (lp) {
lp-&gt;netdev-&gt;dev.tbusy = 0;
mark_bh(NET_BH); <FONT COLOR=#0000FF>/* OK .. we are ready to send buffers */</FONT>
}
}
is-&gt;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-&gt;huptimer;
<FONT COLOR="#298C52">if</FONT> ((r = <A HREF="#set_arg">set_arg</A>((<FONT COLOR="#298C52">void</FONT> *) arg, &amp;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, &amp;val, <FONT COLOR="#298C52">sizeof</FONT>(val) )))
<FONT COLOR="#298C52">return</FONT> r;
is-&gt;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, &amp;val, <FONT COLOR="#298C52">sizeof</FONT>(val) )))
<FONT COLOR="#298C52">return</FONT> r;
val++;
<FONT COLOR="#298C52">if</FONT> (is-&gt;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-&gt;debug &amp; 0x1)
printk(KERN_DEBUG <FONT COLOR="#FF0000">"ippp, ioctl: changed MAXCID to %ld\n"</FONT>, val);
is-&gt;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-&gt;slcomp)
slhc_free(is-&gt;slcomp);
is-&gt;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, &amp;is-&gt;debug, <FONT COLOR="#298C52">sizeof</FONT>(is-&gt;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, &amp;val, <FONT COLOR="#298C52">sizeof</FONT>(val) )))
<FONT COLOR="#298C52">return</FONT> r;
is-&gt;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-&gt;num / (<FONT COLOR="#298C52">sizeof</FONT>(<FONT COLOR="#298C52">long</FONT>)*8);
i = ipc-&gt;num % (<FONT COLOR="#298C52">sizeof</FONT>(<FONT COLOR="#298C52">long</FONT>)*8);
<FONT COLOR="#298C52">if</FONT>(j &lt; 8)
protos[j] |= (0x1&lt;&lt;i);
ipc = ipc-&gt;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, &amp;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, &amp;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> *) &amp;pci,0,<FONT COLOR="#298C52">sizeof</FONT>(<FONT COLOR="#298C52">struct</FONT> pppcallinfo));
<FONT COLOR="#298C52">if</FONT>(lp)
{
strncpy(pci.local_num,lp-&gt;msn,63);
<FONT COLOR="#298C52">if</FONT>(lp-&gt;dial) {
strncpy(pci.remote_num,lp-&gt;dial-&gt;num,63);
}
pci.charge_units = lp-&gt;charge;
<FONT COLOR="#298C52">if</FONT>(lp-&gt;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-&gt;flags &amp; <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,&amp;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-&gt;private_data;
<FONT COLOR="#298C52">if</FONT> (is-&gt;debug &amp; 0x2)
printk(KERN_DEBUG <FONT COLOR="#FF0000">"isdn_ppp_poll: minor: %d\n"</FONT>,
MINOR(file-&gt;f_dentry-&gt;d_inode-&gt;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, &amp;is-&gt;wq, wait);
<FONT COLOR="#298C52">if</FONT> (!(is-&gt;state &amp; <A HREF="isdn_ppp.h.shtml#IPPP_OPEN">IPPP_OPEN</A>)) {
<FONT COLOR="#298C52">if</FONT>(is-&gt;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-&gt;last;
bf = is-&gt;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-&gt;next != bl || (is-&gt;state &amp; <A HREF="isdn_ppp.h.shtml#IPPP_NOBLOCK">IPPP_NOBLOCK</A>)) {
is-&gt;state &amp;= ~<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 &lt; 0 || slot &gt;= <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-&gt;state &amp; <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 &gt;&gt; 8;
nbuf[3] = proto &amp; 0xff;
memcpy(nbuf + 4, buf, len);
save_flags(flags);
<A HREF="kdebug.h.shtml#cli">cli</A>();
bf = is-&gt;first;
bl = is-&gt;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-&gt;next;
kfree(bf-&gt;buf);
is-&gt;first = bf;
}
bl-&gt;buf = (<FONT COLOR="#298C52">char</FONT> *) nbuf;
bl-&gt;len = len + 4;
is-&gt;last = bl-&gt;next;
<A HREF="kdebug.h.shtml#restore_flags">restore_flags</A>(flags);
<FONT COLOR="#298C52">if</FONT> (is-&gt;wq)
wake_up_interruptible(&amp;is-&gt;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-&gt;private_data;
<FONT COLOR="#298C52">if</FONT> (!(is-&gt;state &amp; <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-&gt;first-&gt;next;
save_buf = b-&gt;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-&gt;len &lt; count)
count = b-&gt;len;
b-&gt;buf = NULL;
is-&gt;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-&gt;private_data;
<FONT COLOR="#298C52">if</FONT> (!(is-&gt;state &amp; <A HREF="isdn_ppp.h.shtml#IPPP_CONNECT">IPPP_CONNECT</A>))
<FONT COLOR="#298C52">return</FONT> 0;
lp = is-&gt;lp;
<FONT COLOR=#0000FF>/* -&gt; 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-&gt;huptimer = 0;
<FONT COLOR=#A521F7>#endif</FONT>
<FONT COLOR="#298C52">if</FONT> (lp-&gt;isdn_device &lt; 0 || lp-&gt;isdn_channel &lt; 0)
<FONT COLOR="#298C52">return</FONT> 0;
<FONT COLOR="#298C52">if</FONT> (dev-&gt;drv[lp-&gt;isdn_device]-&gt;running &amp;&amp; lp-&gt;dialstate == 0 &amp;&amp;
(lp-&gt;flags &amp; <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-&gt;debug &amp; 0x40) {
printk(KERN_DEBUG <FONT COLOR="#FF0000">"ppp xmit: len %d\n"</FONT>, (<FONT COLOR="#298C52">int</FONT>) skb-&gt;len);
<A HREF="#isdn_ppp_frame_log">isdn_ppp_frame_log</A>(<FONT COLOR="#FF0000">"xmit"</FONT>, skb-&gt;data, skb-&gt;len, 32,is-&gt;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>, &amp;lp-&gt;netdev-&gt;dev, skb-&gt;data, 0);
<FONT COLOR=#A521F7>#endif</FONT>
<A HREF="#isdn_ppp_send_ccp">isdn_ppp_send_ccp</A>(lp-&gt;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-&gt;isdn_device, lp-&gt;isdn_channel, 1, skb)) != count) {
<FONT COLOR="#298C52">if</FONT> (lp-&gt;sav_skb) {
dev_kfree_skb(lp-&gt;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-&gt;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 &lt; <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 &lt; 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]-&gt;state = 0;
ippp_table[i]-&gt;first = ippp_table[i]-&gt;rq + <A HREF="../includes/isdn_ppp.h.shtml#NUM_RCV_BUFFS">NUM_RCV_BUFFS</A> - 1;
ippp_table[i]-&gt;last = ippp_table[i]-&gt;rq;
<FONT COLOR="#298C52">for</FONT> (j = 0; j &lt; <A HREF="../includes/isdn_ppp.h.shtml#NUM_RCV_BUFFS">NUM_RCV_BUFFS</A>; j++) {
ippp_table[i]-&gt;rq[j].buf = NULL;
ippp_table[i]-&gt;rq[j].last = ippp_table[i]-&gt;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]-&gt;rq[j].next = ippp_table[i]-&gt;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 &lt; <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-&gt;data[0] &amp; 0x1) {
proto = skb-&gt;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-&gt;data[0] &lt;&lt; 8) + skb-&gt;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-&gt;ppp_slot];
<FONT COLOR="#298C52">if</FONT> (is-&gt;debug &amp; 0x4) {
printk(KERN_DEBUG <FONT COLOR="#FF0000">"ippp_receive: len: %d\n"</FONT>, (<FONT COLOR="#298C52">int</FONT>) skb-&gt;len);
<A HREF="#isdn_ppp_frame_log">isdn_ppp_frame_log</A>(<FONT COLOR="#FF0000">"receive"</FONT>, skb-&gt;data, skb-&gt;len, 32,is-&gt;unit);
}
<FONT COLOR="#298C52">if</FONT> (net_dev-&gt;local-&gt;master) {
printk(KERN_WARNING <FONT COLOR="#FF0000">"isdn_ppp_receice: net_dev != master\n"</FONT>);
net_dev = ((isdn_net_local *) net_dev-&gt;local-&gt;master-&gt;priv)-&gt;netdev;
}
<FONT COLOR="#298C52">if</FONT> (skb-&gt;data[0] == 0xff &amp;&amp; skb-&gt;data[1] == 0x03)
skb_pull(skb, 2);
<FONT COLOR="#298C52">else</FONT> <FONT COLOR="#298C52">if</FONT> (is-&gt;pppcfg &amp; 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-&gt;mpppcfg &amp; <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-&gt;compflags &amp; <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-&gt;debug &amp; 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-&gt;data[0];
<FONT COLOR="#298C52">if</FONT> (is-&gt;debug &amp; 0x8)
printk(KERN_DEBUG <FONT COLOR="#FF0000">"recv: %d/%04x/%d -&gt; %02x %02x %02x %02x %02x %02x\n"</FONT>, lp-&gt;ppp_slot, proto,
(<FONT COLOR="#298C52">int</FONT>) skb-&gt;len, (<FONT COLOR="#298C52">int</FONT>) skb-&gt;data[0], (<FONT COLOR="#298C52">int</FONT>) skb-&gt;data[1], (<FONT COLOR="#298C52">int</FONT>) skb-&gt;data[2],
(<FONT COLOR="#298C52">int</FONT>) skb-&gt;data[3], (<FONT COLOR="#298C52">int</FONT>) skb-&gt;data[4], (<FONT COLOR="#298C52">int</FONT>) skb-&gt;data[5]);
<FONT COLOR="#298C52">if</FONT> (!(is-&gt;mpppcfg &amp; <A HREF="../includes/isdn_ppp.h.shtml#SC_IN_SHORT_SEQ">SC_IN_SHORT_SEQ</A>)) {
sqno = ((<FONT COLOR="#298C52">int</FONT>) skb-&gt;data[1] &lt;&lt; 16) + ((<FONT COLOR="#298C52">int</FONT>) skb-&gt;data[2] &lt;&lt; 8) + (<FONT COLOR="#298C52">int</FONT>) skb-&gt;data[3];
skb_pull(skb, 4);
} <FONT COLOR="#298C52">else</FONT> {
sqno = (((<FONT COLOR="#298C52">int</FONT>) skb-&gt;data[0] &amp; 0xf) &lt;&lt; 8) + (<FONT COLOR="#298C52">int</FONT>) skb-&gt;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-&gt;last_link_seqno) &gt;= sqno) {
<FONT COLOR="#298C52">int</FONT> range = is-&gt;range;
<FONT COLOR="#298C52">if</FONT> (tseq + 1024 &lt; 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-&gt;last_link_seqno = sqno;
}
} <FONT COLOR="#298C52">else</FONT> {
<FONT COLOR=#0000FF>/* here, we should also add an redundancy check */</FONT>
is-&gt;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-&gt;queue;;) {
<FONT COLOR="#298C52">long</FONT> lls = ippp_table[lpq-&gt;ppp_slot]-&gt;last_link_seqno;
<FONT COLOR="#298C52">if</FONT> (lls &gt;= 0 &amp;&amp; lls &lt; min_sqno)
min_sqno = lls;
lpq = lpq-&gt;next;
<FONT COLOR="#298C52">if</FONT> (lpq == net_dev-&gt;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 &gt;= ippp_table[lpq-&gt;ppp_slot]-&gt;range) {
<FONT COLOR="#298C52">int</FONT> mask = ippp_table[lpq-&gt;ppp_slot]-&gt;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-&gt;ib.next_num &amp;= mask;
{
<FONT COLOR="#298C52">struct</FONT> sqqueue *q = net_dev-&gt;ib.sq;
<FONT COLOR="#298C52">while</FONT> (q) {
q-&gt;sqno_start &amp;= mask;
q-&gt;sqno_end &amp;= mask;
}
}
min_sqno &amp;= mask;
<FONT COLOR="#298C52">for</FONT> (lpq = net_dev-&gt;queue;;) {
ippp_table[lpq-&gt;ppp_slot]-&gt;last_link_seqno &amp;= mask;
lpq = lpq-&gt;next;
<FONT COLOR="#298C52">if</FONT> (lpq == net_dev-&gt;queue)
<FONT COLOR="#298C52">break</FONT>;
}
}
<FONT COLOR="#298C52">if</FONT> ((BEbyte &amp; (<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-&gt;ppp_slot);
dmes = 1;
}
<FONT COLOR="#298C52">if</FONT> ((sqno_end = <A HREF="#isdn_ppp_fill_mpqueue">isdn_ppp_fill_mpqueue</A>(net_dev, &amp;skb, BEbyte, &amp;sqno, min_sqno)) &lt; 0) {
net_dev-&gt;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-&gt;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-&gt;debug &amp; 0x40)
printk(KERN_DEBUG <FONT COLOR="#FF0000">"min_sqno: %ld sqno_end %d next: %ld\n"</FONT>, min_sqno, sqno_end, net_dev-&gt;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-&gt;ib.modify = 1; <FONT COLOR=#0000FF>/* block timeout-timer */</FONT>
<FONT COLOR="#298C52">if</FONT> (net_dev-&gt;ib.bundled &amp;&amp; net_dev-&gt;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-&gt;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-&gt;skb = skb;
q-&gt;sqno_end = sqno_end;
q-&gt;sqno_start = sqno;
q-&gt;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-&gt;ib.sq) {
net_dev-&gt;ib.sq = q;
q-&gt;next = NULL;
} <FONT COLOR="#298C52">else</FONT> {
<FONT COLOR="#298C52">struct</FONT> sqqueue *ql = net_dev-&gt;ib.sq;
<FONT COLOR="#298C52">if</FONT> (ql-&gt;sqno_start &gt; q-&gt;sqno_start) {
q-&gt;next = ql;
net_dev-&gt;ib.sq = q;
} <FONT COLOR="#298C52">else</FONT> {
<FONT COLOR="#298C52">while</FONT> (ql-&gt;next &amp;&amp; ql-&gt;next-&gt;sqno_start &lt; q-&gt;sqno_start)
ql = ql-&gt;next;
q-&gt;next = ql-&gt;next;
ql-&gt;next = q;
}
}
} <FONT COLOR="#298C52">else</FONT> {
<FONT COLOR=#0000FF>/*
* packet was 'in order' .. push it higher
*/</FONT>
net_dev-&gt;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-&gt;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 = &amp;net_dev-&gt;dev;
<FONT COLOR="#298C52">struct</FONT> ippp_struct *is = ippp_table[lp-&gt;ppp_slot];
<FONT COLOR="#298C52">if</FONT> (is-&gt;debug &amp; 0x10) {
printk(KERN_DEBUG <FONT COLOR="#FF0000">"push, skb %d %04x\n"</FONT>, (<FONT COLOR="#298C52">int</FONT>) skb-&gt;len, proto);
<A HREF="#isdn_ppp_frame_log">isdn_ppp_frame_log</A>(<FONT COLOR="#FF0000">"rpush"</FONT>, skb-&gt;data, skb-&gt;len, 32,is-&gt;unit);
}
<FONT COLOR="#298C52">if</FONT>(proto == PPP_COMP) {
<FONT COLOR="#298C52">if</FONT>(!lp-&gt;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-&gt;master-&gt;priv))-&gt;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-&gt;debug &amp; 0x10) {
printk(KERN_DEBUG <FONT COLOR="#FF0000">"RPostDecomp, skb %d %04x\n"</FONT>, (<FONT COLOR="#298C52">int</FONT>) skb-&gt;len, proto);
<A HREF="#isdn_ppp_frame_log">isdn_ppp_frame_log</A>(<FONT COLOR="#FF0000">"R-Decomp"</FONT>, skb-&gt;data, skb-&gt;len, 32,is-&gt;unit);
}
}
<FONT COLOR="#298C52">else</FONT> <FONT COLOR="#298C52">if</FONT>(is-&gt;compflags &amp; <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-&gt;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-&gt;master-&gt;priv))-&gt;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-&gt;debug &amp; 0x20)
printk(KERN_DEBUG <FONT COLOR="#FF0000">"isdn_ppp: IPX\n"</FONT>);
skb-&gt;dev = dev;
skb-&gt;mac.raw = skb-&gt;data;
skb-&gt;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-&gt;debug &amp; 0x20)
printk(KERN_DEBUG <FONT COLOR="#FF0000">"isdn_ppp: VJC_UNCOMP\n"</FONT>);
<FONT COLOR="#298C52">if</FONT> (slhc_remember(ippp_table[net_dev-&gt;local-&gt;ppp_slot]-&gt;slcomp, skb-&gt;data, skb-&gt;len) &lt;= 0) {
printk(KERN_WARNING <FONT COLOR="#FF0000">"isdn_ppp: received illegal VJC_UNCOMP frame!\n"</FONT>);
net_dev-&gt;local-&gt;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-&gt;debug &amp; 0x20)
printk(KERN_DEBUG <FONT COLOR="#FF0000">"isdn_ppp: IP\n"</FONT>);
skb-&gt;dev = dev;
skb-&gt;mac.raw = skb-&gt;data;
skb-&gt;protocol = htons(ETH_P_IP);
<FONT COLOR="#298C52">break</FONT>;
<FONT COLOR="#298C52">case</FONT> PPP_VJC_COMP:
<FONT COLOR="#298C52">if</FONT> (is-&gt;debug &amp; 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-&gt;len + 40);
<FONT COLOR="#298C52">if</FONT> (!skb) {
printk(KERN_WARNING <FONT COLOR="#FF0000">"%s: Memory squeeze, dropping packet.\n"</FONT>, dev-&gt;<A HREF="isdn_common.c.shtml#name">name</A>);
net_dev-&gt;local-&gt;stats.rx_dropped++;
dev_kfree_skb(skb_old);
<FONT COLOR="#298C52">return</FONT>;
}
skb-&gt;dev = dev;
skb_put(skb, skb_old-&gt;len + 40);
memcpy(skb-&gt;data, skb_old-&gt;data, skb_old-&gt;len);
skb-&gt;mac.raw = skb-&gt;data;
pkt_len = slhc_uncompress(ippp_table[net_dev-&gt;local-&gt;ppp_slot]-&gt;slcomp,
skb-&gt;data, skb_old-&gt;len);
dev_kfree_skb(skb_old);
<FONT COLOR="#298C52">if</FONT> (pkt_len &lt; 0) {
dev_kfree_skb(skb);
lp-&gt;stats.rx_dropped++;
<FONT COLOR="#298C52">return</FONT>;
}
skb_trim(skb, pkt_len);
skb-&gt;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-&gt;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-&gt;data, proto);
<FONT COLOR=#A521F7>#endif</FONT>
<A HREF="#isdn_ppp_fill_rq">isdn_ppp_fill_rq</A>(skb-&gt;data, skb-&gt;len, proto, lp-&gt;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-&gt;huptimer = 0;
<FONT COLOR=#A521F7>#endif</FONT>
netif_rx(skb);
<FONT COLOR=#0000FF>/* net_dev-&gt;local-&gt;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) &lt; 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-&gt;priv))-&gt;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-&gt;priv);
<FONT COLOR="#298C52">else</FONT> {
mdev = dev;
mlp = (isdn_net_local *) (dev-&gt;priv);
}
nd = mlp-&gt;netdev; <FONT COLOR=#0000FF>/* get master lp */</FONT>
ipts = ippp_table[mlp-&gt;ppp_slot];
<FONT COLOR="#298C52">if</FONT> (!(ipts-&gt;pppcfg &amp; SC_ENABLE_IP)) { <FONT COLOR=#0000FF>/* PPP connected ? */</FONT>
<FONT COLOR=#A521F7>#ifdef</FONT> ISDN_SYNCPPP_READDRESS
<FONT COLOR="#298C52">if</FONT> (!ipts-&gt;old_pa_addr)
ipts-&gt;old_pa_addr = mdev-&gt;pa_addr;
<FONT COLOR="#298C52">if</FONT> (!ipts-&gt;old_pa_dstaddr)
ipts-&gt;old_pa_dstaddr = mdev-&gt;pa_dstaddr;
<FONT COLOR=#A521F7>#endif</FONT>
<FONT COLOR="#298C52">if</FONT> (ipts-&gt;debug &amp; 0x1)
printk(KERN_INFO <FONT COLOR="#FF0000">"%s: IP frame delayed.\n"</FONT>, dev-&gt;<A HREF="isdn_common.c.shtml#name">name</A>);
<FONT COLOR="#298C52">return</FONT> 1;
}
<FONT COLOR="#298C52">switch</FONT> (ntohs(skb-&gt;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-&gt;old_pa_addr != mdev-&gt;pa_addr) {
<FONT COLOR="#298C52">struct</FONT> iphdr *ipfr;
ipfr = (<FONT COLOR="#298C52">struct</FONT> iphdr *) skb-&gt;data;
<FONT COLOR="#298C52">if</FONT>(ipts-&gt;debug &amp; 0x4)
printk(KERN_DEBUG <FONT COLOR="#FF0000">"IF-address changed from %lx to %lx\n"</FONT>, ipts-&gt;old_pa_addr, mdev-&gt;pa_addr);
<FONT COLOR="#298C52">if</FONT> (ipfr-&gt;version == 4) {
<FONT COLOR="#298C52">if</FONT> (ipfr-&gt;saddr == ipts-&gt;old_pa_addr) {
printk(KERN_DEBUG <FONT COLOR="#FF0000">"readdressing %lx to %lx\n"</FONT>, ipfr-&gt;saddr, mdev-&gt;pa_addr);
ipfr-&gt;saddr = mdev-&gt;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-&gt;protocol);
<FONT COLOR="#298C52">return</FONT> 0;
}
lp = nd-&gt;queue; <FONT COLOR=#0000FF>/* get lp on top of queue */</FONT>
<FONT COLOR="#298C52">if</FONT> (lp-&gt;sav_skb) { <FONT COLOR=#0000FF>/* find a non-busy device */</FONT>
isdn_net_local *nlp = lp-&gt;next;
<FONT COLOR="#298C52">while</FONT> (lp-&gt;sav_skb) {
<FONT COLOR="#298C52">if</FONT> (lp == nlp)
<FONT COLOR="#298C52">return</FONT> 1;
nlp = nd-&gt;queue = nd-&gt;queue-&gt;next;
}
lp = nlp;
}
ipt = ippp_table[lp-&gt;ppp_slot];
<FONT COLOR=#A521F7>#ifndef</FONT> CONFIG_ISDN_TIMEOUT_RULES
lp-&gt;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-&gt;debug &amp; 0x4)
printk(KERN_DEBUG <FONT COLOR="#FF0000">"xmit skb, len %d\n"</FONT>, (<FONT COLOR="#298C52">int</FONT>) skb-&gt;len);
<FONT COLOR="#298C52">if</FONT> (ipts-&gt;debug &amp; 0x40)
<A HREF="#isdn_ppp_frame_log">isdn_ppp_frame_log</A>(<FONT COLOR="#FF0000">"xmit0"</FONT>, skb-&gt;data, skb-&gt;len, 32,ipts-&gt;unit);
<FONT COLOR=#A521F7>#ifdef</FONT> CONFIG_ISDN_PPP_VJ
<FONT COLOR="#298C52">if</FONT> (proto == PPP_IP &amp;&amp; ipts-&gt;pppcfg &amp; 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-&gt;len);
<FONT COLOR="#298C52">if</FONT> (new_skb) {
u_char *buf;
<FONT COLOR="#298C52">int</FONT> pktlen;
new_skb-&gt;dev = skb-&gt;dev;
skb_put(new_skb, skb-&gt;len);
buf = skb-&gt;data;
pktlen = slhc_compress(ipts-&gt;slcomp, skb-&gt;data, skb-&gt;len, new_skb-&gt;data,
&amp;buf, !(ipts-&gt;pppcfg &amp; SC_NO_TCP_CCID));
<FONT COLOR="#298C52">if</FONT> (buf != skb-&gt;data) {
<FONT COLOR="#298C52">if</FONT> (new_skb-&gt;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-&gt;data[0] &amp; SL_TYPE_COMPRESSED_TCP) { <FONT COLOR=#0000FF>/* cslip? style -&gt; PPP */</FONT>
proto = PPP_VJC_COMP;
skb-&gt;data[0] ^= SL_TYPE_COMPRESSED_TCP;
} <FONT COLOR="#298C52">else</FONT> {
<FONT COLOR="#298C52">if</FONT> (skb-&gt;data[0] &gt;= SL_TYPE_UNCOMPRESSED_TCP)
proto = PPP_VJC_UNCOMP;
skb-&gt;data[0] = (skb-&gt;data[0] &amp; 0x0f) | 0x40;
}
}
}
<FONT COLOR=#A521F7>#endif</FONT>
<FONT COLOR=#0000FF>/*
* normal (single link) or bundle compression
*/</FONT>
<FONT COLOR="#298C52">if</FONT>(ipts-&gt;compflags &amp; <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,&amp;proto,ipt,ipts,0);
<FONT COLOR="#298C52">if</FONT> (ipt-&gt;debug &amp; 0x24)
printk(KERN_DEBUG <FONT COLOR="#FF0000">"xmit2 skb, len %d, proto %04x\n"</FONT>, (<FONT COLOR="#298C52">int</FONT>) skb-&gt;len, proto);
<FONT COLOR=#A521F7>#ifdef</FONT> CONFIG_ISDN_MPP
<FONT COLOR="#298C52">if</FONT> (ipt-&gt;mpppcfg &amp; <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-&gt;mp_seqno;
ipts-&gt;mp_seqno++;
nd-&gt;queue = nd-&gt;queue-&gt;next;
<FONT COLOR="#298C52">if</FONT> (ipt-&gt;mpppcfg &amp; <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>(&amp;skb, 3);
<FONT COLOR="#298C52">if</FONT>(!data)
<FONT COLOR="#298C52">return</FONT> 0;
mp_seqno &amp;= 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 &gt;&gt; 8) &amp; 0xf); <FONT COLOR=#0000FF>/* (B)egin &amp; (E)ndbit .. */</FONT>
data[1] = mp_seqno &amp; 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>(&amp;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 &amp; (E)ndbit .. */</FONT>
data[1] = (mp_seqno &gt;&gt; 16) &amp; 0xff; <FONT COLOR=#0000FF>/* sequence number: 24bit */</FONT>
data[2] = (mp_seqno &gt;&gt; 8) &amp; 0xff;
data[3] = (mp_seqno &gt;&gt; 0) &amp; 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-&gt;compflags &amp; <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,&amp;proto,ipt,ipts,1);
<FONT COLOR="#298C52">if</FONT>( (ipt-&gt;pppcfg &amp; SC_COMP_PROT) &amp;&amp; (proto &lt;= 0xff) ) {
<FONT COLOR="#298C52">unsigned</FONT> <FONT COLOR="#298C52">char</FONT> *data = <A HREF="#isdn_ppp_skb_push">isdn_ppp_skb_push</A>(&amp;skb,1);
<FONT COLOR="#298C52">if</FONT>(!data)
<FONT COLOR="#298C52">return</FONT> 0;
data[0] = proto &amp; 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>(&amp;skb,2);
<FONT COLOR="#298C52">if</FONT>(!data)
<FONT COLOR="#298C52">return</FONT> 0;
data[0] = (proto &gt;&gt; 8) &amp; 0xff;
data[1] = proto &amp; 0xff;
}
<FONT COLOR="#298C52">if</FONT>(!(ipt-&gt;pppcfg &amp; 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>(&amp;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-&gt;debug &amp; 0x40) {
printk(KERN_DEBUG <FONT COLOR="#FF0000">"skb xmit: len: %d\n"</FONT>, (<FONT COLOR="#298C52">int</FONT>) skb-&gt;len);
<A HREF="#isdn_ppp_frame_log">isdn_ppp_frame_log</A>(<FONT COLOR="#FF0000">"xmit"</FONT>, skb-&gt;data, skb-&gt;len, 32,ipts-&gt;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-&gt;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-&gt;<A HREF="isdn_common.c.shtml#name">name</A>);
dev_kfree_skb(skb);
} <FONT COLOR="#298C52">else</FONT>
lp-&gt;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-&gt;ib.sq;
p-&gt;ib.sq = NULL;
<FONT COLOR="#298C52">while</FONT> (q) {
<FONT COLOR="#298C52">struct</FONT> sqqueue *qn = q-&gt;next;
<FONT COLOR="#298C52">if</FONT> (q-&gt;skb)
dev_kfree_skb(q-&gt;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-&gt;mp_last;
p-&gt;mp_last = NULL;
<FONT COLOR="#298C52">while</FONT> (q) {
<FONT COLOR="#298C52">struct</FONT> mpqueue *ql = q-&gt;next;
dev_kfree_skb(q-&gt;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-&gt;lp;
lp = p-&gt;queue;
p-&gt;ib.bundled = 1;
nlp-&gt;last = lp-&gt;last;
lp-&gt;last-&gt;next = nlp;
lp-&gt;last = nlp;
nlp-&gt;next = lp;
p-&gt;queue = nlp;
ippp_table[nlp-&gt;ppp_slot]-&gt;unit = ippp_table[lp-&gt;ppp_slot]-&gt;unit;
<FONT COLOR=#0000FF>/* maybe also SC_CCP stuff */</FONT>
ippp_table[nlp-&gt;ppp_slot]-&gt;pppcfg |= ippp_table[lp-&gt;ppp_slot]-&gt;pppcfg &amp;
(SC_ENABLE_IP | SC_NO_TCP_CCID | SC_REJ_COMP_TCP);
ippp_table[nlp-&gt;ppp_slot]-&gt;mpppcfg |= ippp_table[lp-&gt;ppp_slot]-&gt;mpppcfg &amp;
(<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-&gt;ppp_slot]-&gt;mpppcfg != ippp_table[lp-&gt;ppp_slot]-&gt;mpppcfg) {
printk(KERN_WARNING <FONT COLOR="#FF0000">"isdn_ppp_bundle: different MP options %04x and %04x\n"</FONT>,
ippp_table[nlp-&gt;ppp_slot]-&gt;mpppcfg, ippp_table[lp-&gt;ppp_slot]-&gt;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-&gt;mp_last;
<FONT COLOR="#298C52">while</FONT> (q) {
q-&gt;sqno &amp;= mask;
q = q-&gt;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-&gt;skb = *skb;
q1-&gt;sqno = sqno;
q1-&gt;BEbyte = BEbyte;
q1-&gt;time = jiffies;
save_flags(flags);
<A HREF="kdebug.h.shtml#cli">cli</A>();
<FONT COLOR="#298C52">if</FONT> (!(q = dev-&gt;mp_last)) {
dev-&gt;mp_last = q1;
q1-&gt;next = NULL;
q1-&gt;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 &gt; q-&gt;sqno) {
<FONT COLOR="#298C52">if</FONT> (q-&gt;next) {
q = q-&gt;next;
<FONT COLOR="#298C52">continue</FONT>;
}
q-&gt;next = q1;
q1-&gt;next = NULL;
q1-&gt;last = q;
<FONT COLOR="#298C52">break</FONT>;
}
<FONT COLOR="#298C52">if</FONT> (sqno == q-&gt;sqno)
printk(KERN_WARNING <FONT COLOR="#FF0000">"isdn_fill_mpqueue: illegal sqno received!!\n"</FONT>);
q1-&gt;last = q-&gt;last;
q1-&gt;next = q;
<FONT COLOR="#298C52">if</FONT> (q-&gt;last) {
q-&gt;last-&gt;next = q1;
} <FONT COLOR="#298C52">else</FONT>
dev-&gt;mp_last = q1;
q-&gt;last = q1;
<FONT COLOR="#298C52">break</FONT>;
}
<FONT COLOR=#0000FF>/* now we check whether we completed a packet with this fragment */</FONT>
pktlen = -q1-&gt;skb-&gt;len;
q = q1;
cnt = q1-&gt;sqno;
<FONT COLOR="#298C52">while</FONT> (!(q-&gt;BEbyte &amp; <A HREF="../includes/isdn_ppp.h.shtml#MP_END_FRAG">MP_END_FRAG</A>)) {
cnt++;
<FONT COLOR="#298C52">if</FONT> (!(q-&gt;next) || q-&gt;next-&gt;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-&gt;skb-&gt;len;
q = q-&gt;next;
}
pktlen += q-&gt;skb-&gt;len;
qe = q;
q = q1;
cnt = q1-&gt;sqno;
<FONT COLOR="#298C52">while</FONT> (!(q-&gt;BEbyte &amp; <A HREF="../includes/isdn_ppp.h.shtml#MP_BEGIN_FRAG">MP_BEGIN_FRAG</A>)) {
cnt--;
<FONT COLOR="#298C52">if</FONT> (!(q-&gt;last) || q-&gt;last-&gt;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-&gt;skb-&gt;len;
q = q-&gt;last;
}
pktlen += q-&gt;skb-&gt;len;
<FONT COLOR="#298C52">if</FONT> (q-&gt;last)
q-&gt;last-&gt;next = qe-&gt;next;
<FONT COLOR="#298C52">else</FONT>
dev-&gt;mp_last = qe-&gt;next;
<FONT COLOR="#298C52">if</FONT> (qe-&gt;next)
qe-&gt;next-&gt;last = q-&gt;last;
qe-&gt;next = NULL;
sqno_end = qe-&gt;sqno;
*sqnop = q-&gt;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-&gt;next;
dev_kfree_skb(q-&gt;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-&gt;next;
memcpy((*skb)-&gt;data + cnt, q-&gt;skb-&gt;data, q-&gt;skb-&gt;len);
cnt += q-&gt;skb-&gt;len;
dev_kfree_skb(q-&gt;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-&gt;ib.sq) &amp;&amp; (q-&gt;sqno_start == net_dev-&gt;ib.next_num || q-&gt;sqno_end &lt;= min_sqno)) {
<FONT COLOR="#298C52">int</FONT> proto;
<FONT COLOR="#298C52">if</FONT> (q-&gt;sqno_start != net_dev-&gt;ib.next_num) {
printk(KERN_DEBUG <FONT COLOR="#FF0000">"ippp: MP, stepping over missing frame: %ld\n"</FONT>, net_dev-&gt;ib.next_num);
<FONT COLOR=#A521F7>#ifdef</FONT> CONFIG_ISDN_PPP_VJ
slhc_toss(ippp_table[net_dev-&gt;local-&gt;ppp_slot]-&gt;slcomp);
<FONT COLOR=#A521F7>#endif</FONT>
}
proto = <A HREF="#isdn_ppp_strip_proto">isdn_ppp_strip_proto</A>(q-&gt;skb);
<A HREF="#isdn_ppp_push_higher">isdn_ppp_push_higher</A>(net_dev, lp, q-&gt;skb, proto);
net_dev-&gt;ib.sq = q-&gt;next;
net_dev-&gt;ib.next_num = q-&gt;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&lt;=min_sqno: auch rauswerfen
wenn sqno&lt;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-&gt;mp_last;
<FONT COLOR="#298C52">while</FONT>(q &amp;&amp; (q-&gt;sqno &lt; min_sqno) ) {
<FONT COLOR="#298C52">if</FONT> ( (q-&gt;BEbyte &amp; <A HREF="../includes/isdn_ppp.h.shtml#MP_END_FRAG">MP_END_FRAG</A>) ||
(q-&gt;next &amp;&amp; (q-&gt;next-&gt;sqno &lt;= min_sqno) &amp;&amp; (q-&gt;next-&gt;BEbyte &amp; <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-&gt;mp_last = q-&gt;next))
q-&gt;next-&gt;last = NULL;
<FONT COLOR="#298C52">while</FONT> (q) {
ql = q-&gt;last;
printk(KERN_DEBUG <FONT COLOR="#FF0000">"ippp, freeing packet with sqno: %ld\n"</FONT>,q-&gt;sqno);
dev_kfree_skb(q-&gt;skb);
kfree(q);
<FONT COLOR=#A521F7>#ifdef</FONT> CONFIG_ISDN_PPP_VJ
toss = 1;
<FONT COLOR=#A521F7>#endif</FONT>
q = ql;
}
q = dev-&gt;mp_last;
} <FONT COLOR="#298C52">else</FONT>
q = q-&gt;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-&gt;local-&gt;ppp_slot]-&gt;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-&gt;netdev;
<FONT COLOR="#298C52">struct</FONT> sqqueue *q,
*ql = NULL,
*qn;
<FONT COLOR="#298C52">while</FONT> (net_dev) {
isdn_net_local *lp = net_dev-&gt;local;
<FONT COLOR="#298C52">if</FONT> (net_dev-&gt;ib.modify || lp-&gt;master) { <FONT COLOR=#0000FF>/* interface locked or slave? */</FONT>
net_dev = net_dev-&gt;next;
<FONT COLOR="#298C52">continue</FONT>;
}
q = net_dev-&gt;ib.sq;
<FONT COLOR="#298C52">while</FONT> (q) {
<FONT COLOR="#298C52">if</FONT> (q-&gt;sqno_start == net_dev-&gt;ib.next_num || q-&gt;timer &lt; 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-&gt;sqno_start != net_dev-&gt;ib.next_num)
slhc_toss(ippp_table[lp-&gt;ppp_slot]-&gt;slcomp);
<FONT COLOR=#A521F7>#endif</FONT>
ql = net_dev-&gt;ib.sq;
net_dev-&gt;ib.sq = q-&gt;next;
net_dev-&gt;ib.next_num = q-&gt;sqno_end + 1;
q-&gt;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-&gt;skb);
<A HREF="#isdn_ppp_push_higher">isdn_ppp_push_higher</A>(net_dev, lp, ql-&gt;skb, proto);
qn = ql-&gt;next;
kfree(ql);
ql = qn;
}
q = net_dev-&gt;ib.sq;
} <FONT COLOR="#298C52">else</FONT>
q = q-&gt;next;
}
net_dev = net_dev-&gt;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-&gt;priv;
<FONT COLOR="#298C52">int</FONT> err;
res = (<FONT COLOR="#298C52">struct</FONT> ppp_stats *) ifr-&gt;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(&amp;t, 0, <FONT COLOR="#298C52">sizeof</FONT>(<FONT COLOR="#298C52">struct</FONT> ppp_stats));
<FONT COLOR="#298C52">if</FONT> (dev-&gt;flags &amp; IFF_UP) {
t.p.ppp_ipackets = lp-&gt;stats.rx_packets;
t.p.ppp_ierrors = lp-&gt;stats.rx_errors;
t.p.ppp_opackets = lp-&gt;stats.tx_packets;
t.p.ppp_oerrors = lp-&gt;stats.tx_errors;
<FONT COLOR=#A521F7>#ifdef</FONT> CONFIG_ISDN_PPP_VJ
<FONT COLOR="#298C52">if</FONT> (slot &gt;= 0 &amp;&amp; ippp_table[slot]-&gt;slcomp) {
<FONT COLOR="#298C52">struct</FONT> slcompress *slcomp = ippp_table[slot]-&gt;slcomp;
t.vj.vjs_packets = slcomp-&gt;sls_o_compressed + slcomp-&gt;sls_o_uncompressed;
t.vj.vjs_compressed = slcomp-&gt;sls_o_compressed;
t.vj.vjs_searches = slcomp-&gt;sls_o_searches;
t.vj.vjs_misses = slcomp-&gt;sls_o_misses;
t.vj.vjs_errorin = slcomp-&gt;sls_i_error;
t.vj.vjs_tossed = slcomp-&gt;sls_i_tossed;
t.vj.vjs_uncompressedin = slcomp-&gt;sls_i_uncompressed;
t.vj.vjs_compressedin = slcomp-&gt;sls_i_compressed;
}
<FONT COLOR=#A521F7>#endif</FONT>
}
<FONT COLOR="#298C52">if</FONT>( copy_to_user(res, &amp;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-&gt;priv;
<FONT COLOR=#A521F7>#if</FONT> 0
printk(KERN_DEBUG <FONT COLOR="#FF0000">"ippp, dev_ioctl: cmd %#08x , %d \n"</FONT>, cmd, lp-&gt;ppp_slot);
<FONT COLOR=#A521F7>#endif</FONT>
<FONT COLOR="#298C52">if</FONT> (lp-&gt;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-&gt;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-&gt;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 &gt; 8)
<FONT COLOR="#298C52">return</FONT> -1;
<FONT COLOR="#298C52">for</FONT> (i = 0, deci = 1; i &lt; 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 &gt;= <FONT COLOR="#FF0000">'0'</FONT> &amp;&amp; a &lt;= <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-&gt;local;
<FONT COLOR="#298C52">if</FONT> (!(lp-&gt;flags &amp; <A HREF="../includes/isdn.h.shtml#ISDN_NET_CONNECTED">ISDN_NET_CONNECTED</A>))
<FONT COLOR="#298C52">return</FONT> 5;
sdev = lp-&gt;slave;
<FONT COLOR="#298C52">while</FONT> (sdev) {
isdn_net_local *mlp = (isdn_net_local *) sdev-&gt;priv;
<FONT COLOR="#298C52">if</FONT> (!(mlp-&gt;flags &amp; <A HREF="../includes/isdn.h.shtml#ISDN_NET_CONNECTED">ISDN_NET_CONNECTED</A>))
<FONT COLOR="#298C52">break</FONT>;
sdev = mlp-&gt;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-&gt;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-&gt;local;
<FONT COLOR="#298C52">if</FONT> (!(lp-&gt;flags &amp; <A HREF="../includes/isdn.h.shtml#ISDN_NET_CONNECTED">ISDN_NET_CONNECTED</A>))
<FONT COLOR="#298C52">return</FONT> 5;
sdev = lp-&gt;slave;
<FONT COLOR="#298C52">while</FONT> (sdev) {
isdn_net_local *mlp = (isdn_net_local *) sdev-&gt;priv;
<FONT COLOR="#298C52">if</FONT> ((mlp-&gt;flags &amp; <A HREF="../includes/isdn.h.shtml#ISDN_NET_CONNECTED">ISDN_NET_CONNECTED</A>))
<FONT COLOR="#298C52">break</FONT>;
sdev = mlp-&gt;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-&gt;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-&gt;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-&gt;link_decomp_stat;
ipc = is-&gt;link_decompressor;
}
<FONT COLOR="#298C52">else</FONT> {
<FONT COLOR=#0000FF>/*
* 'normal' or bundle-compression
*/</FONT>
<FONT COLOR="#298C52">if</FONT>(!master-&gt;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-&gt;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-&gt;decomp_stat;
ipc = master-&gt;decompressor;
}
printk(KERN_DEBUG <FONT COLOR="#FF0000">"ippp: Decompress valid!\n"</FONT>);
<FONT COLOR="#298C52">if</FONT>((master &amp;&amp; proto == PPP_COMP) || (!master &amp;&amp; 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-&gt;decompress(stat,skb,skb_out);
dev_kfree_skb(skb);
<FONT COLOR="#298C52">if</FONT>(len &lt;= 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-&gt;unit);
ipc-&gt;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 &lt; 0 || *proto &gt; 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 =&gt; Link compression */</FONT>
<FONT COLOR=#A521F7>#if</FONT> 0
compressor = is-&gt;link_compressor;
stat = is-&gt;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-&gt;compressor;
stat = is-&gt;comp_stat;
}
<FONT COLOR="#298C52">else</FONT> {
compressor = master-&gt;compressor;
stat = master-&gt;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-&gt;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-&gt;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-&gt;ppp_slot];
<FONT COLOR="#298C52">struct</FONT> ippp_struct *mis;
<FONT COLOR="#298C52">if</FONT>(lp-&gt;master)
mis = ippp_table[((isdn_net_local *) (lp-&gt;master-&gt;priv))-&gt;ppp_slot];
<FONT COLOR="#298C52">else</FONT>
mis = is;
<FONT COLOR="#298C52">switch</FONT>(skb-&gt;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-&gt;debug &amp; 0x10)
printk(KERN_DEBUG <FONT COLOR="#FF0000">"Disable (de)compression here!\n"</FONT>);
<FONT COLOR="#298C52">if</FONT>(proto == PPP_CCP)
mis-&gt;compflags &amp;= ~(<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-&gt;compflags &amp;= ~(<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-&gt;debug &amp; 0x10)
printk(KERN_DEBUG <FONT COLOR="#FF0000">"Enable decompression here!\n"</FONT>);
<FONT COLOR="#298C52">if</FONT>(proto == PPP_CCP)
mis-&gt;compflags |= <A HREF="../includes/isdn_ppp.h.shtml#SC_DECOMP_ON">SC_DECOMP_ON</A>;
<FONT COLOR="#298C52">else</FONT>
is-&gt;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-&gt;debug &amp; 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-&gt;decompressor &amp;&amp; mis-&gt;decomp_stat)
mis-&gt;decompressor-&gt;reset(mis-&gt;decomp_stat);
mis-&gt;compflags &amp;= ~<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-&gt;link_decompressor &amp;&amp; is-&gt;link_decomp_stat)
is-&gt;link_decompressor-&gt;reset(is-&gt;link_decomp_stat);
is-&gt;compflags &amp;= ~<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-&gt;ppp_slot];
<FONT COLOR="#298C52">int</FONT> proto;
<FONT COLOR="#298C52">if</FONT>(!skb || skb-&gt;len &lt; 3)
<FONT COLOR="#298C52">return</FONT>;
proto = ((<FONT COLOR="#298C52">int</FONT>)skb-&gt;data[0]&lt;&lt;8)+skb-&gt;data[1];
<FONT COLOR="#298C52">if</FONT>(proto != PPP_CCP &amp;&amp; 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-&gt;master)
mis = ippp_table[((isdn_net_local *) (lp-&gt;master-&gt;priv))-&gt;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-&gt;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-&gt;debug &amp; 0x10)
printk(KERN_DEBUG <FONT COLOR="#FF0000">"Disable (de)compression here!\n"</FONT>);
<FONT COLOR="#298C52">if</FONT>(proto == PPP_CCP)
is-&gt;compflags &amp;= ~(<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-&gt;compflags &amp;= ~(<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-&gt;debug &amp; 0x10)
printk(KERN_DEBUG <FONT COLOR="#FF0000">"Enable compression here!\n"</FONT>);
<FONT COLOR="#298C52">if</FONT>(proto == PPP_CCP)
is-&gt;compflags |= <A HREF="../includes/isdn_ppp.h.shtml#SC_COMP_ON">SC_COMP_ON</A>;
<FONT COLOR="#298C52">else</FONT>
is-&gt;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-&gt;debug &amp; 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-&gt;compressor &amp;&amp; is-&gt;comp_stat)
is-&gt;compressor-&gt;reset(is-&gt;comp_stat);
is-&gt;compflags &amp;= ~<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-&gt;link_compressor &amp;&amp; is-&gt;link_comp_stat)
is-&gt;link_compressor-&gt;reset(is-&gt;link_comp_stat);
is-&gt;compflags &amp;= ~<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-&gt;next = ipc_head;
ipc-&gt;prev = NULL;
<FONT COLOR="#298C52">if</FONT>(ipc_head) {
ipc_head-&gt;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-&gt;prev)
ipc-&gt;prev-&gt;next = ipc-&gt;next;
<FONT COLOR="#298C52">else</FONT>
ipc_head = ipc-&gt;next;
<FONT COLOR="#298C52">if</FONT>(ipc-&gt;next)
ipc-&gt;next-&gt;prev = ipc-&gt;prev;
ipc-&gt;prev = ipc-&gt;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-&gt;num;
<FONT COLOR="#298C52">if</FONT>(is-&gt;debug &amp; 0x10)
printk(KERN_DEBUG <FONT COLOR="#FF0000">"[%d] Set %s type %d\n"</FONT>,is-&gt;unit,
(data-&gt;flags&amp;<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-&gt;num == num) {
stat = ipc-&gt;alloc(data);
<FONT COLOR="#298C52">if</FONT>(stat) {
ret = ipc-&gt;init(stat,data,is-&gt;unit,0);
<FONT COLOR="#298C52">if</FONT>(!ret) {
printk(KERN_ERR <FONT COLOR="#FF0000">"Can't init (de)compression!\n"</FONT>);
ipc-&gt;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-&gt;flags &amp; <A HREF="../includes/isdn_ppp.h.shtml#IPPP_COMP_FLAG_XMIT">IPPP_COMP_FLAG_XMIT</A>) {
<FONT COLOR="#298C52">if</FONT>(data-&gt;flags &amp; <A HREF="../includes/isdn_ppp.h.shtml#IPPP_COMP_FLAG_LINK">IPPP_COMP_FLAG_LINK</A>) {
<FONT COLOR="#298C52">if</FONT>(is-&gt;link_comp_stat)
is-&gt;link_compressor-&gt;free(is-&gt;link_comp_stat);
is-&gt;link_comp_stat = stat;
is-&gt;link_compressor = ipc;
}
<FONT COLOR="#298C52">else</FONT> {
<FONT COLOR="#298C52">if</FONT>(is-&gt;comp_stat)
is-&gt;compressor-&gt;free(is-&gt;comp_stat);
is-&gt;comp_stat = stat;
is-&gt;compressor = ipc;
}
}
<FONT COLOR="#298C52">else</FONT> {
<FONT COLOR="#298C52">if</FONT>(data-&gt;flags &amp; <A HREF="../includes/isdn_ppp.h.shtml#IPPP_COMP_FLAG_LINK">IPPP_COMP_FLAG_LINK</A>) {
<FONT COLOR="#298C52">if</FONT>(is-&gt;link_decomp_stat)
is-&gt;link_decompressor-&gt;free(is-&gt;link_decomp_stat);
is-&gt;link_decomp_stat = stat;
is-&gt;link_decompressor = ipc;
}
<FONT COLOR="#298C52">else</FONT> {
<FONT COLOR="#298C52">if</FONT>(is-&gt;decomp_stat)
is-&gt;decompressor-&gt;free(is-&gt;decomp_stat);
is-&gt;decomp_stat = stat;
is-&gt;decompressor = ipc;
}
}
<FONT COLOR="#298C52">return</FONT> 0;
}
ipc = ipc-&gt;next;
}
<FONT COLOR="#298C52">return</FONT> -EINVAL;
}
</BODY>
</HTML>