Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
dffdfbce
Commit
dffdfbce
authored
Sep 28, 2002
by
Kai Germaschewski
Browse files
Options
Browse Files
Download
Plain Diff
Merge zephyr:src/kernel/v2.5/linux-2.5.isdn
into tp1.ruhr-uni-bochum.de:/home/kai/kernel/v2.5/linux-2.5.isdn
parents
cbe45702
c25b65fe
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
1225 additions
and
1076 deletions
+1225
-1076
drivers/isdn/i4l/Makefile
drivers/isdn/i4l/Makefile
+2
-1
drivers/isdn/i4l/isdn_ciscohdlck.c
drivers/isdn/i4l/isdn_ciscohdlck.c
+407
-0
drivers/isdn/i4l/isdn_ciscohdlck.h
drivers/isdn/i4l/isdn_ciscohdlck.h
+16
-0
drivers/isdn/i4l/isdn_common.c
drivers/isdn/i4l/isdn_common.c
+0
-2
drivers/isdn/i4l/isdn_common.h
drivers/isdn/i4l/isdn_common.h
+2
-0
drivers/isdn/i4l/isdn_concap.c
drivers/isdn/i4l/isdn_concap.c
+142
-0
drivers/isdn/i4l/isdn_concap.h
drivers/isdn/i4l/isdn_concap.h
+46
-1
drivers/isdn/i4l/isdn_net.c
drivers/isdn/i4l/isdn_net.c
+507
-1045
drivers/isdn/i4l/isdn_net.h
drivers/isdn/i4l/isdn_net.h
+23
-1
drivers/isdn/i4l/isdn_ppp.c
drivers/isdn/i4l/isdn_ppp.c
+46
-8
drivers/isdn/i4l/isdn_ppp.h
drivers/isdn/i4l/isdn_ppp.h
+29
-8
include/linux/isdn.h
include/linux/isdn.h
+5
-8
include/linux/isdn_ppp.h
include/linux/isdn_ppp.h
+0
-2
No files found.
drivers/isdn/i4l/Makefile
View file @
dffdfbce
...
...
@@ -12,7 +12,8 @@ obj-$(CONFIG_ISDN_PPP_BSDCOMP) += isdn_bsdcomp.o
# Multipart objects.
isdn-objs
:=
isdn_net.o isdn_tty.o
\
isdn_v110.o isdn_common.o
isdn_v110.o isdn_common.o
\
isdn_ciscohdlck.o
# Optional parts of multipart objects.
...
...
drivers/isdn/i4l/isdn_ciscohdlck.c
0 → 100644
View file @
dffdfbce
/*
* Linux ISDN subsystem, CISCO HDLC network interfaces
*
* Copyright 1994-1998 by Fritz Elfert (fritz@isdn4linux.de)
* 1995,96 by Thinking Objects Software GmbH Wuerzburg
* 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
* 1999-2002 by Kai Germaschewski <kai@germaschewski.name>
* 2001 by Bjoern A. Zeeb <i4l@zabbadoz.net>
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
* For info on the protocol, see http://i4l.zabbadoz.net/i4l/cisco-hdlc.txt
*/
#include "isdn_common.h"
#include "isdn_net.h"
#include "isdn_ciscohdlck.h"
#include <linux/inetdevice.h>
/*
* CISCO HDLC keepalive specific stuff
*/
static
struct
sk_buff
*
isdn_net_ciscohdlck_alloc_skb
(
isdn_net_local
*
lp
,
int
len
)
{
unsigned
short
hl
=
isdn_slot_hdrlen
(
lp
->
isdn_slot
);
struct
sk_buff
*
skb
;
skb
=
alloc_skb
(
hl
+
len
,
GFP_ATOMIC
);
if
(
!
skb
)
{
printk
(
"isdn out of mem at %s:%d!
\n
"
,
__FILE__
,
__LINE__
);
return
0
;
}
skb_reserve
(
skb
,
hl
);
return
skb
;
}
/* cisco hdlck device private ioctls */
static
int
isdn_ciscohdlck_dev_ioctl
(
struct
net_device
*
dev
,
struct
ifreq
*
ifr
,
int
cmd
)
{
isdn_net_local
*
lp
=
(
isdn_net_local
*
)
dev
->
priv
;
unsigned
long
len
=
0
;
unsigned
long
expires
=
0
;
int
tmp
=
0
;
int
period
=
lp
->
cisco_keepalive_period
;
char
debserint
=
lp
->
cisco_debserint
;
int
rc
=
0
;
if
(
lp
->
p_encap
!=
ISDN_NET_ENCAP_CISCOHDLCK
)
return
-
EINVAL
;
switch
(
cmd
)
{
/* get/set keepalive period */
case
SIOCGKEEPPERIOD
:
len
=
(
unsigned
long
)
sizeof
(
lp
->
cisco_keepalive_period
);
if
(
copy_to_user
((
char
*
)
ifr
->
ifr_ifru
.
ifru_data
,
(
int
*
)
&
lp
->
cisco_keepalive_period
,
len
))
rc
=
-
EFAULT
;
break
;
case
SIOCSKEEPPERIOD
:
tmp
=
lp
->
cisco_keepalive_period
;
len
=
(
unsigned
long
)
sizeof
(
lp
->
cisco_keepalive_period
);
if
(
copy_from_user
((
int
*
)
&
period
,
(
char
*
)
ifr
->
ifr_ifru
.
ifru_data
,
len
))
rc
=
-
EFAULT
;
if
((
period
>
0
)
&&
(
period
<=
32767
))
lp
->
cisco_keepalive_period
=
period
;
else
rc
=
-
EINVAL
;
if
(
!
rc
&&
(
tmp
!=
lp
->
cisco_keepalive_period
))
{
expires
=
(
unsigned
long
)(
jiffies
+
lp
->
cisco_keepalive_period
*
HZ
);
mod_timer
(
&
lp
->
cisco_timer
,
expires
);
printk
(
KERN_INFO
"%s: Keepalive period set "
"to %d seconds.
\n
"
,
lp
->
name
,
lp
->
cisco_keepalive_period
);
}
break
;
/* get/set debugging */
case
SIOCGDEBSERINT
:
len
=
(
unsigned
long
)
sizeof
(
lp
->
cisco_debserint
);
if
(
copy_to_user
((
char
*
)
ifr
->
ifr_ifru
.
ifru_data
,
(
char
*
)
&
lp
->
cisco_debserint
,
len
))
rc
=
-
EFAULT
;
break
;
case
SIOCSDEBSERINT
:
len
=
(
unsigned
long
)
sizeof
(
lp
->
cisco_debserint
);
if
(
copy_from_user
((
char
*
)
&
debserint
,
(
char
*
)
ifr
->
ifr_ifru
.
ifru_data
,
len
))
rc
=
-
EFAULT
;
if
((
debserint
>=
0
)
&&
(
debserint
<=
64
))
lp
->
cisco_debserint
=
debserint
;
else
rc
=
-
EINVAL
;
break
;
default:
rc
=
-
EINVAL
;
break
;
}
return
(
rc
);
}
/* called via cisco_timer.function */
static
void
isdn_net_ciscohdlck_slarp_send_keepalive
(
unsigned
long
data
)
{
isdn_net_local
*
lp
=
(
isdn_net_local
*
)
data
;
struct
sk_buff
*
skb
;
unsigned
char
*
p
;
unsigned
long
last_cisco_myseq
=
lp
->
cisco_myseq
;
int
myseq_diff
=
0
;
lp
->
cisco_myseq
++
;
myseq_diff
=
(
lp
->
cisco_myseq
-
lp
->
cisco_mineseen
);
if
((
lp
->
cisco_line_state
)
&&
((
myseq_diff
>=
3
)
||
(
myseq_diff
<=
-
3
)))
{
/* line up -> down */
lp
->
cisco_line_state
=
0
;
printk
(
KERN_WARNING
"UPDOWN: Line protocol on Interface %s,"
" changed state to down
\n
"
,
lp
->
name
);
/* should stop routing higher-level data accross */
}
else
if
((
!
lp
->
cisco_line_state
)
&&
(
myseq_diff
>=
0
)
&&
(
myseq_diff
<=
2
))
{
/* line down -> up */
lp
->
cisco_line_state
=
1
;
printk
(
KERN_WARNING
"UPDOWN: Line protocol on Interface %s,"
" changed state to up
\n
"
,
lp
->
name
);
/* restart routing higher-level data accross */
}
if
(
lp
->
cisco_debserint
)
printk
(
KERN_DEBUG
"%s: HDLC "
"myseq %lu, mineseen %lu%c, yourseen %lu, %s
\n
"
,
lp
->
name
,
last_cisco_myseq
,
lp
->
cisco_mineseen
,
((
last_cisco_myseq
==
lp
->
cisco_mineseen
)
?
'*'
:
040
),
lp
->
cisco_yourseq
,
((
lp
->
cisco_line_state
)
?
"line up"
:
"line down"
));
skb
=
isdn_net_ciscohdlck_alloc_skb
(
lp
,
4
+
14
);
if
(
!
skb
)
return
;
p
=
skb_put
(
skb
,
4
+
14
);
/* cisco header */
p
+=
put_u8
(
p
,
CISCO_ADDR_UNICAST
);
p
+=
put_u8
(
p
,
CISCO_CTRL
);
p
+=
put_u16
(
p
,
CISCO_TYPE_SLARP
);
/* slarp keepalive */
p
+=
put_u32
(
p
,
CISCO_SLARP_KEEPALIVE
);
p
+=
put_u32
(
p
,
lp
->
cisco_myseq
);
p
+=
put_u32
(
p
,
lp
->
cisco_yourseq
);
p
+=
put_u16
(
p
,
0xffff
);
// reliablity, always 0xffff
isdn_net_write_super
(
lp
,
skb
);
lp
->
cisco_timer
.
expires
=
jiffies
+
lp
->
cisco_keepalive_period
*
HZ
;
add_timer
(
&
lp
->
cisco_timer
);
}
static
void
isdn_net_ciscohdlck_slarp_send_request
(
isdn_net_local
*
lp
)
{
struct
sk_buff
*
skb
;
unsigned
char
*
p
;
skb
=
isdn_net_ciscohdlck_alloc_skb
(
lp
,
4
+
14
);
if
(
!
skb
)
return
;
p
=
skb_put
(
skb
,
4
+
14
);
/* cisco header */
p
+=
put_u8
(
p
,
CISCO_ADDR_UNICAST
);
p
+=
put_u8
(
p
,
CISCO_CTRL
);
p
+=
put_u16
(
p
,
CISCO_TYPE_SLARP
);
/* slarp request */
p
+=
put_u32
(
p
,
CISCO_SLARP_REQUEST
);
p
+=
put_u32
(
p
,
0
);
// address
p
+=
put_u32
(
p
,
0
);
// netmask
p
+=
put_u16
(
p
,
0
);
// unused
isdn_net_write_super
(
lp
,
skb
);
}
static
void
isdn_ciscohdlck_connected
(
isdn_net_local
*
lp
)
{
lp
->
cisco_myseq
=
0
;
lp
->
cisco_mineseen
=
0
;
lp
->
cisco_yourseq
=
0
;
lp
->
cisco_keepalive_period
=
ISDN_TIMER_KEEPINT
;
lp
->
cisco_last_slarp_in
=
0
;
lp
->
cisco_line_state
=
0
;
lp
->
cisco_debserint
=
0
;
if
(
lp
->
p_encap
==
ISDN_NET_ENCAP_CISCOHDLCK
)
{
/* send slarp request because interface/seq.no.s reset */
isdn_net_ciscohdlck_slarp_send_request
(
lp
);
init_timer
(
&
lp
->
cisco_timer
);
lp
->
cisco_timer
.
data
=
(
unsigned
long
)
lp
;
lp
->
cisco_timer
.
function
=
isdn_net_ciscohdlck_slarp_send_keepalive
;
lp
->
cisco_timer
.
expires
=
jiffies
+
lp
->
cisco_keepalive_period
*
HZ
;
add_timer
(
&
lp
->
cisco_timer
);
}
isdn_net_device_wake_queue
(
lp
);
}
static
void
isdn_ciscohdlck_disconnected
(
isdn_net_local
*
lp
)
{
if
(
lp
->
p_encap
==
ISDN_NET_ENCAP_CISCOHDLCK
)
{
del_timer
(
&
lp
->
cisco_timer
);
}
}
static
void
isdn_net_ciscohdlck_slarp_send_reply
(
isdn_net_local
*
lp
)
{
struct
sk_buff
*
skb
;
unsigned
char
*
p
;
struct
in_device
*
in_dev
=
NULL
;
u32
addr
=
0
;
/* local ipv4 address */
u32
mask
=
0
;
/* local netmask */
if
((
in_dev
=
lp
->
netdev
->
dev
.
ip_ptr
)
!=
NULL
)
{
/* take primary(first) address of interface */
struct
in_ifaddr
*
ifa
=
in_dev
->
ifa_list
;
if
(
ifa
!=
NULL
)
{
addr
=
ifa
->
ifa_local
;
mask
=
ifa
->
ifa_mask
;
}
}
skb
=
isdn_net_ciscohdlck_alloc_skb
(
lp
,
4
+
14
);
if
(
!
skb
)
return
;
p
=
skb_put
(
skb
,
4
+
14
);
/* cisco header */
p
+=
put_u8
(
p
,
CISCO_ADDR_UNICAST
);
p
+=
put_u8
(
p
,
CISCO_CTRL
);
p
+=
put_u16
(
p
,
CISCO_TYPE_SLARP
);
/* slarp reply, send own ip/netmask; if values are nonsense remote
* should think we are unable to provide it with an address via SLARP */
p
+=
put_u32
(
p
,
CISCO_SLARP_REPLY
);
p
+=
put_u32
(
p
,
addr
);
// address
p
+=
put_u32
(
p
,
mask
);
// netmask
p
+=
put_u16
(
p
,
0
);
// unused
isdn_net_write_super
(
lp
,
skb
);
}
static
void
isdn_net_ciscohdlck_slarp_in
(
isdn_net_local
*
lp
,
struct
sk_buff
*
skb
)
{
unsigned
char
*
p
;
int
period
;
u32
code
;
u32
my_seq
,
addr
;
u32
your_seq
,
mask
;
u32
local
;
u16
unused
;
if
(
skb
->
len
<
14
)
return
;
p
=
skb
->
data
;
p
+=
get_u32
(
p
,
&
code
);
switch
(
code
)
{
case
CISCO_SLARP_REQUEST
:
lp
->
cisco_yourseq
=
0
;
isdn_net_ciscohdlck_slarp_send_reply
(
lp
);
break
;
case
CISCO_SLARP_REPLY
:
addr
=
ntohl
(
*
(
u32
*
)
p
);
mask
=
ntohl
(
*
(
u32
*
)(
p
+
4
));
if
(
mask
!=
0xfffffffc
)
goto
slarp_reply_out
;
if
((
addr
&
3
)
==
0
||
(
addr
&
3
)
==
3
)
goto
slarp_reply_out
;
local
=
addr
^
3
;
printk
(
KERN_INFO
"%s: got slarp reply: "
"remote ip: %d.%d.%d.%d, "
"local ip: %d.%d.%d.%d "
"mask: %d.%d.%d.%d
\n
"
,
lp
->
name
,
HIPQUAD
(
addr
),
HIPQUAD
(
local
),
HIPQUAD
(
mask
));
break
;
slarp_reply_out:
printk
(
KERN_INFO
"%s: got invalid slarp "
"reply (%d.%d.%d.%d/%d.%d.%d.%d) "
"- ignored
\n
"
,
lp
->
name
,
HIPQUAD
(
addr
),
HIPQUAD
(
mask
));
break
;
case
CISCO_SLARP_KEEPALIVE
:
period
=
(
int
)((
jiffies
-
lp
->
cisco_last_slarp_in
+
HZ
/
2
-
1
)
/
HZ
);
if
(
lp
->
cisco_debserint
&&
(
period
!=
lp
->
cisco_keepalive_period
)
&&
lp
->
cisco_last_slarp_in
)
{
printk
(
KERN_DEBUG
"%s: Keepalive period mismatch - "
"is %d but should be %d.
\n
"
,
lp
->
name
,
period
,
lp
->
cisco_keepalive_period
);
}
lp
->
cisco_last_slarp_in
=
jiffies
;
p
+=
get_u32
(
p
,
&
my_seq
);
p
+=
get_u32
(
p
,
&
your_seq
);
p
+=
get_u16
(
p
,
&
unused
);
lp
->
cisco_yourseq
=
my_seq
;
lp
->
cisco_mineseen
=
your_seq
;
break
;
}
}
static
void
isdn_ciscohdlck_receive
(
isdn_net_dev
*
idev
,
isdn_net_local
*
olp
,
struct
sk_buff
*
skb
)
{
isdn_net_local
*
lp
=
&
idev
->
local
;
unsigned
char
*
p
;
u8
addr
;
u8
ctrl
;
u16
type
;
if
(
skb
->
len
<
4
)
goto
out_free
;
p
=
skb
->
data
;
p
+=
get_u8
(
p
,
&
addr
);
p
+=
get_u8
(
p
,
&
ctrl
);
p
+=
get_u16
(
p
,
&
type
);
skb_pull
(
skb
,
4
);
if
((
addr
!=
CISCO_ADDR_UNICAST
&&
addr
!=
CISCO_ADDR_BROADCAST
)
||
ctrl
!=
CISCO_CTRL
)
{
printk
(
KERN_DEBUG
"%s: Unknown Cisco header %#02x %#02x
\n
"
,
lp
->
name
,
addr
,
ctrl
);
goto
out_free
;
}
switch
(
type
)
{
case
CISCO_TYPE_SLARP
:
isdn_net_ciscohdlck_slarp_in
(
lp
,
skb
);
goto
out_free
;
case
CISCO_TYPE_CDP
:
if
(
lp
->
cisco_debserint
)
printk
(
KERN_DEBUG
"%s: Received CDP packet. use "
"
\"
no cdp enable
\"
on cisco.
\n
"
,
lp
->
name
);
goto
out_free
;
default:
/* no special cisco protocol */
isdn_net_reset_huptimer
(
lp
,
olp
);
skb
->
protocol
=
htons
(
type
);
netif_rx
(
skb
);
return
;
}
out_free:
kfree_skb
(
skb
);
}
static
int
isdn_ciscohdlck_header
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
,
unsigned
short
type
,
void
*
daddr
,
void
*
saddr
,
unsigned
plen
)
{
unsigned
char
*
p
=
skb_push
(
skb
,
4
);
p
+=
put_u8
(
p
,
CISCO_ADDR_UNICAST
);
p
+=
put_u8
(
p
,
CISCO_CTRL
);
p
+=
put_u16
(
p
,
type
);
return
4
;
}
int
isdn_ciscohdlck_setup
(
isdn_net_dev
*
p
)
{
p
->
dev
.
hard_header
=
isdn_ciscohdlck_header
;
p
->
dev
.
hard_header_cache
=
NULL
;
p
->
dev
.
header_cache_update
=
NULL
;
p
->
dev
.
flags
=
IFF_NOARP
|
IFF_POINTOPOINT
;
p
->
dev
.
do_ioctl
=
isdn_ciscohdlck_dev_ioctl
;
p
->
local
.
receive
=
isdn_ciscohdlck_receive
;
p
->
local
.
connected
=
isdn_ciscohdlck_connected
;
p
->
local
.
disconnected
=
isdn_ciscohdlck_disconnected
;
return
0
;
}
drivers/isdn/i4l/isdn_ciscohdlck.h
0 → 100644
View file @
dffdfbce
/*
* Linux ISDN subsystem, CISCO HDLC network interfaces
*
* Copyright 1999-2002 by Kai Germaschewski <kai@germaschewski.name>
* 2001 by Bjoern A. Zeeb <i4l@zabbadoz.net>
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*/
#ifndef ISDN_CISCOHDLCK_H
#define ISDN_CISCOHDLCK_H
int
isdn_ciscohdlck_setup
(
isdn_net_dev
*
p
);
#endif
drivers/isdn/i4l/isdn_common.c
View file @
dffdfbce
...
...
@@ -611,11 +611,9 @@ isdn_status_callback(isdn_ctrl * c)
dbg_statcallb
(
"BHUP: %d
\n
"
,
i
);
dev
->
drv
[
di
]
->
online
&=
~
(
1
<<
(
c
->
arg
));
isdn_info_update
();
#ifdef CONFIG_ISDN_X25
/* Signal hangup to network-devices */
if
(
isdn_net_stat_callback
(
i
,
c
))
break
;
#endif
isdn_v110_stat_callback
(
&
slot
[
i
].
iv110
,
c
);
if
(
isdn_tty_stat_callback
(
i
,
c
))
break
;
...
...
drivers/isdn/i4l/isdn_common.h
View file @
dffdfbce
...
...
@@ -12,6 +12,8 @@
*
*/
#include <linux/isdn.h>
#undef ISDN_DEBUG_MODEM_OPEN
#undef ISDN_DEBUG_MODEM_IOCTL
#undef ISDN_DEBUG_MODEM_WAITSENT
...
...
drivers/isdn/i4l/isdn_concap.c
View file @
dffdfbce
...
...
@@ -106,3 +106,145 @@ struct concap_proto * isdn_concap_new( int encap )
}
return
NULL
;
}
void
isdn_x25_cleanup
(
isdn_net_dev
*
p
)
{
isdn_net_local
*
lp
=
&
p
->
local
;
struct
concap_proto
*
cprot
=
p
->
cprot
;
unsigned
long
flags
;
/* delete old encapsulation protocol if present ... */
save_flags
(
flags
);
cli
();
/* avoid races with incoming events trying to
call cprot->pops methods */
if
(
cprot
&&
cprot
->
pops
)
cprot
->
pops
->
proto_del
(
cprot
);
p
->
cprot
=
NULL
;
lp
->
dops
=
NULL
;
restore_flags
(
flags
);
}
void
isdn_x25_open
(
struct
net_device
*
dev
)
{
struct
concap_device_ops
*
dops
=
(
(
isdn_net_local
*
)
dev
->
priv
)
->
dops
;
struct
concap_proto
*
cprot
=
(
(
isdn_net_local
*
)
dev
->
priv
)
->
netdev
->
cprot
;
unsigned
long
flags
;
save_flags
(
flags
);
cli
();
/* Avoid glitch on writes to CMD regs */
if
(
cprot
&&
cprot
->
pops
&&
dops
)
cprot
->
pops
->
restart
(
cprot
,
dev
,
dops
);
restore_flags
(
flags
);
}
void
isdn_x25_close
(
struct
net_device
*
dev
)
{
struct
concap_proto
*
cprot
=
(
(
isdn_net_local
*
)
dev
->
priv
)
->
netdev
->
cprot
;
if
(
cprot
&&
cprot
->
pops
)
cprot
->
pops
->
close
(
cprot
);
}
static
void
isdn_x25_connected
(
isdn_net_local
*
lp
)
{
struct
concap_proto
*
cprot
=
lp
->
netdev
->
cprot
;
struct
concap_proto_ops
*
pops
=
cprot
?
cprot
->
pops
:
0
;
/* try if there are generic concap receiver routines */
if
(
pops
)
if
(
pops
->
connect_ind
)
pops
->
connect_ind
(
cprot
);
isdn_net_device_wake_queue
(
lp
);
}
static
void
isdn_x25_disconnected
(
isdn_net_local
*
lp
)
{
struct
concap_proto
*
cprot
=
lp
->
netdev
->
cprot
;
struct
concap_proto_ops
*
pops
=
cprot
?
cprot
->
pops
:
0
;
/* try if there are generic encap protocol
receiver routines and signal the closure of
the link */
if
(
pops
&&
pops
->
disconn_ind
)
pops
->
disconn_ind
(
cprot
);
}
int
isdn_x25_start_xmit
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
)
{
/* At this point hard_start_xmit() passes control to the encapsulation
protocol (if present).
For X.25 auto-dialing is completly bypassed because:
- It does not conform with the semantics of a reliable datalink
service as needed by X.25 PLP.
- I don't want that the interface starts dialing when the network layer
sends a message which requests to disconnect the lapb link (or if it
sends any other message not resulting in data transmission).
Instead, dialing will be initiated by the encapsulation protocol entity
when a dl_establish request is received from the upper layer.
*/
isdn_net_local
*
lp
=
(
isdn_net_local
*
)
dev
->
priv
;
struct
concap_proto
*
cprot
=
lp
->
netdev
->
cprot
;
int
ret
=
cprot
->
pops
->
encap_and_xmit
(
cprot
,
skb
);
if
(
ret
)
netif_stop_queue
(
dev
);
return
ret
;
}
static
void
isdn_x25_receive
(
isdn_net_dev
*
p
,
isdn_net_local
*
olp
,
struct
sk_buff
*
skb
)
{
isdn_net_local
*
lp
=
&
p
->
local
;
struct
concap_proto
*
cprot
=
lp
->
netdev
->
cprot
;
/* try if there are generic sync_device receiver routines */
if
(
cprot
)
if
(
cprot
->
pops
)
if
(
cprot
->
pops
->
data_ind
)
{
cprot
->
pops
->
data_ind
(
cprot
,
skb
);
return
;
}
}
void
isdn_x25_realrm
(
isdn_net_dev
*
p
)
{
if
(
p
->
cprot
&&
p
->
cprot
->
pops
)
p
->
cprot
->
pops
->
proto_del
(
p
->
cprot
);
}
int
isdn_x25_setup
(
isdn_net_dev
*
p
,
int
encap
)
{
isdn_net_local
*
lp
=
&
p
->
local
;
/* ... , prepare for configuration of new one ... */
switch
(
encap
){
case
ISDN_NET_ENCAP_X25IFACE
:
lp
->
dops
=
&
isdn_concap_reliable_dl_dops
;
}
/* ... and allocate new one ... */
p
->
cprot
=
isdn_concap_new
(
cfg
->
p_encap
);
/* p -> cprot == NULL now if p_encap is not supported
by means of the concap_proto mechanism */
if
(
!
p
->
cprot
)
return
-
EINVAL
;
p
->
dev
.
type
=
ARPHRD_X25
;
/* change ARP type */
p
->
dev
.
addr_len
=
0
;
p
->
dev
.
hard_header
=
NULL
;
p
->
dev
.
hard_header_cache
=
NULL
;
p
->
dev
.
header_cache_update
=
NULL
;
p
->
local
.
receive
=
isdn_x25_receive
;
p
->
local
.
connected
=
isdn_x25_connected
;
p
->
local
.
disconnected
=
isdn_x25_disconnected
;
/* the protocol is not configured yet; this will
happen later when isdn_x25_open() is called */
return
0
;
}
#endif
/* CONFIG_ISDN_X25 */
drivers/isdn/i4l/isdn_concap.h
View file @
dffdfbce
...
...
@@ -9,6 +9,51 @@
extern
struct
concap_device_ops
isdn_concap_reliable_dl_dops
;
extern
struct
concap_device_ops
isdn_concap_demand_dial_dops
;
extern
struct
concap_proto
*
isdn_concap_new
(
int
);
struct
concap_proto
*
isdn_concap_new
(
int
);
#ifdef CONFIG_ISDN_X25
int
isdn_x25_setup
(
isdn_net_dev
*
p
,
int
encap
);
void
isdn_x25_cleanup
(
isdn_net_dev
*
p
);
void
isdn_x25_open
(
struct
net_device
*
dev
);
void
isdn_x25_close
(
struct
net_device
*
dev
);
int
isdn_x25_start_xmit
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
);
void
isdn_x25_realrm
(
isdn_net_dev
*
p
);
#else
static
inline
void
isdn_x25_cleanup
(
isdn_net_dev
*
p
)
{
}
static
inline
int
isdn_x25_setup
(
isdn_net_dev
*
p
,
int
encap
)
{
printk
(
KERN_WARNING
"ISDN: X25 support not configured
\n
"
);
return
-
EINVAL
;
}
static
inline
void
isdn_x25_open
(
struct
net_device
*
dev
)
{
}
static
inline
void
isdn_x25_close
(
struct
net_device
*
dev
)
{
}
static
inline
int
isdn_x25_start_xmit
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
)
{
return
0
;
}
static
inline
void
isdn_x25_realrm
(
isdn_net_dev
*
p
)
{
}
#endif
drivers/isdn/i4l/isdn_net.c
View file @
dffdfbce
...
...
@@ -3,8 +3,9 @@
* Linux ISDN subsystem, network interfaces and related functions (linklevel).
*
* Copyright 1994-1998 by Fritz Elfert (fritz@isdn4linux.de)
* Copyright 1995,96 by Thinking Objects Software GmbH Wuerzburg
* Copyright 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
* 1995,96 by Thinking Objects Software GmbH Wuerzburg
* 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
* 1999-2002 by Kai Germaschewski <kai@germaschewski.name>
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
...
...
@@ -17,9 +18,6 @@
* 'V' - accept VOICE (DOV) only
* 'B' - accept BOTH DATA and DOV types
*
* Jan 2001: fix CISCO HDLC Bjoern A. Zeeb <i4l@zabbadoz.net>
* for info on the protocol, see
* http://i4l.zabbadoz.net/i4l/cisco-hdlc.txt
*/
#include <linux/config.h>
...
...
@@ -30,13 +28,10 @@
#include <linux/inetdevice.h>
#include "isdn_common.h"
#include "isdn_net.h"
#ifdef CONFIG_ISDN_PPP
#include "isdn_ppp.h"
#endif
#ifdef CONFIG_ISDN_X25
#include <linux/concap.h>
#include "isdn_concap.h"
#
endif
#
include "isdn_ciscohdlck.h"
enum
{
ST_NULL
,
...
...
@@ -109,18 +104,6 @@ static __inline__ int isdn_net_device_started(isdn_net_dev *n)
return
netif_running
(
dev
);
}
/*
* wake up the network -> net_device queue.
* For slaves, wake the corresponding master interface.
*/
static
__inline__
void
isdn_net_device_wake_queue
(
isdn_net_local
*
lp
)
{
if
(
lp
->
master
)
netif_wake_queue
(
lp
->
master
);
else
netif_wake_queue
(
&
lp
->
netdev
->
dev
);
}
/*
* stop the network -> net_device queue.
* For slaves, stop the corresponding master interface.
...
...
@@ -208,11 +191,13 @@ int isdn_net_force_dial_lp(isdn_net_local *);
static
int
isdn_net_start_xmit
(
struct
sk_buff
*
,
struct
net_device
*
);
static
void
do_dialout
(
isdn_net_local
*
lp
);
static
void
isdn_net_ciscohdlck_connected
(
isdn_net_local
*
lp
);
static
void
isdn_net_ciscohdlck_disconnected
(
isdn_net_local
*
lp
);
static
int
isdn_net_handle_event
(
isdn_net_local
*
lp
,
int
pr
,
void
*
arg
);
static
int
isdn_rawip_setup
(
isdn_net_dev
*
p
);
static
int
isdn_ether_setup
(
isdn_net_dev
*
p
);
static
int
isdn_uihdlc_setup
(
isdn_net_dev
*
p
);
static
int
isdn_iptyp_setup
(
isdn_net_dev
*
p
);
char
*
isdn_net_revision
=
"$Revision: 1.140.6.11 $"
;
/*
...
...
@@ -232,27 +217,6 @@ isdn_net_unreachable(struct net_device *dev, struct sk_buff *skb, char *reason)
dst_link_failure
(
skb
);
}
static
void
isdn_net_reset
(
struct
net_device
*
dev
)
{
#ifdef CONFIG_ISDN_X25
struct
concap_device_ops
*
dops
=
(
(
isdn_net_local
*
)
dev
->
priv
)
->
dops
;
struct
concap_proto
*
cprot
=
(
(
isdn_net_local
*
)
dev
->
priv
)
->
netdev
->
cprot
;
#endif
ulong
flags
;
/* not sure if the cli() is needed at all --KG */
save_flags
(
flags
);
cli
();
/* Avoid glitch on writes to CMD regs */
#ifdef CONFIG_ISDN_X25
if
(
cprot
&&
cprot
->
pops
&&
dops
)
cprot
->
pops
->
restart
(
cprot
,
dev
,
dops
);
#endif
restore_flags
(
flags
);
}
/* Open/initialize the board. */
static
int
isdn_net_open
(
struct
net_device
*
dev
)
...
...
@@ -266,7 +230,7 @@ isdn_net_open(struct net_device *dev)
we need to call netif_start_queue, not netif_wake_queue here */
netif_start_queue
(
dev
);
isdn_
net_reset
(
dev
);
isdn_
x25_open
(
dev
);
/* Fill in the MAC-level header (not needed, but for compatibility... */
for
(
i
=
0
;
i
<
ETH_ALEN
-
sizeof
(
u32
);
i
++
)
dev
->
dev_addr
[
i
]
=
0xfc
;
...
...
@@ -283,7 +247,7 @@ isdn_net_open(struct net_device *dev)
if
((
p
=
(((
isdn_net_local
*
)
dev
->
priv
)
->
slave
)))
{
while
(
p
)
{
isdn_
net_reset
(
p
);
isdn_
x25_open
(
p
);
p
=
(((
isdn_net_local
*
)
p
->
priv
)
->
slave
);
}
}
...
...
@@ -405,16 +369,10 @@ static void isdn_net_lp_disconnected(isdn_net_local *lp)
static
void
isdn_net_connected
(
isdn_net_local
*
lp
)
{
#ifdef CONFIG_ISDN_X25
struct
concap_proto
*
cprot
=
lp
->
netdev
->
cprot
;
struct
concap_proto_ops
*
pops
=
cprot
?
cprot
->
pops
:
0
;
#endif
lp
->
dialstate
=
ST_ACTIVE
;
lp
->
hup_timer
.
expires
=
jiffies
+
HZ
;
add_timer
(
&
lp
->
hup_timer
);
if
(
lp
->
p_encap
==
ISDN_NET_ENCAP_CISCOHDLCK
)
isdn_net_ciscohdlck_connected
(
lp
);
if
(
lp
->
p_encap
!=
ISDN_NET_ENCAP_SYNCPPP
)
{
if
(
lp
->
master
)
{
/* is lp a slave? */
isdn_net_dev
*
nd
=
((
isdn_net_local
*
)
lp
->
master
->
priv
)
->
netdev
;
...
...
@@ -435,19 +393,7 @@ static void isdn_net_connected(isdn_net_local *lp)
lp
->
cps
=
0
;
lp
->
last_jiffies
=
jiffies
;
#ifdef CONFIG_ISDN_PPP
if
(
lp
->
p_encap
==
ISDN_NET_ENCAP_SYNCPPP
)
isdn_ppp_wakeup_daemon
(
lp
);
#endif
#ifdef CONFIG_ISDN_X25
/* try if there are generic concap receiver routines */
if
(
pops
)
if
(
pops
->
connect_ind
)
pops
->
connect_ind
(
cprot
);
#endif
/* CONFIG_ISDN_X25 */
/* ppp needs to do negotiations first */
if
(
lp
->
p_encap
!=
ISDN_NET_ENCAP_SYNCPPP
)
isdn_net_device_wake_queue
(
lp
);
lp
->
connected
(
lp
);
}
/*
...
...
@@ -583,10 +529,6 @@ do_dialout(isdn_net_local *lp)
static
int
isdn_net_handle_event
(
isdn_net_local
*
lp
,
int
pr
,
void
*
arg
)
{
#ifdef CONFIG_ISDN_X25
struct
concap_proto
*
cprot
=
lp
->
netdev
->
cprot
;
struct
concap_proto_ops
*
pops
=
cprot
?
cprot
->
pops
:
0
;
#endif
isdn_net_dev
*
p
=
lp
->
netdev
;
isdn_ctrl
*
c
=
arg
;
isdn_ctrl
cmd
;
...
...
@@ -606,45 +548,19 @@ isdn_net_handle_event(isdn_net_local *lp, int pr, void *arg)
}
break
;
case
ISDN_STAT_DHUP
:
/* Either D-Channel-hangup or error during dialout */
#ifdef CONFIG_ISDN_X25 // FIXME handle != ST_0?
/* If we are not connencted then dialing had
failed. If there are generic encap protocol
receiver routines signal the closure of
the link*/
if
(
!
(
lp
->
flags
&
ISDN_NET_CONNECTED
)
&&
pops
&&
pops
->
disconn_ind
)
pops
->
disconn_ind
(
cprot
);
#endif
/* CONFIG_ISDN_X25 */
if
(
lp
->
flags
&
ISDN_NET_CONNECTED
)
{
if
(
lp
->
p_encap
==
ISDN_NET_ENCAP_CISCOHDLCK
)
isdn_net_ciscohdlck_disconnected
(
lp
);
#ifdef CONFIG_ISDN_PPP
if
(
lp
->
p_encap
==
ISDN_NET_ENCAP_SYNCPPP
)
isdn_ppp_free
(
lp
);
#endif
isdn_net_lp_disconnected
(
lp
);
isdn_slot_all_eaz
(
lp
->
isdn_slot
);
printk
(
KERN_INFO
"%s: remote hangup
\n
"
,
lp
->
name
);
printk
(
KERN_INFO
"%s: Chargesum is %d
\n
"
,
lp
->
name
,
lp
->
charge
);
isdn_net_unbind_channel
(
lp
);
return
1
;
}
break
;
#ifdef CONFIG_ISDN_X25 // FIXME handle != ST_0?
case
ISDN_STAT_BHUP
:
/* B-Channel-hangup */
/* try if there are generic encap protocol
receiver routines and signal the closure of
the link */
if
(
pops
&&
pops
->
disconn_ind
){
pops
->
disconn_ind
(
cprot
);
return
1
;
}
break
;
#endif
/* CONFIG_ISDN_X25 */
if
(
!
(
lp
->
flags
&
ISDN_NET_CONNECTED
))
break
;
if
(
lp
->
disconnected
)
lp
->
disconnected
(
lp
);
isdn_net_lp_disconnected
(
lp
);
isdn_slot_all_eaz
(
lp
->
isdn_slot
);
printk
(
KERN_INFO
"%s: remote hangup
\n
"
,
lp
->
name
);
printk
(
KERN_INFO
"%s: Chargesum is %d
\n
"
,
lp
->
name
,
lp
->
charge
);
isdn_net_unbind_channel
(
lp
);
return
1
;
case
ISDN_STAT_CINF
:
/* Charge-info from TelCo. Calculate interval between
* charge-infos and set timestamp for last info for
...
...
@@ -777,10 +693,6 @@ void
isdn_net_hangup
(
isdn_net_local
*
lp
)
{
isdn_ctrl
cmd
;
#ifdef CONFIG_ISDN_X25
struct
concap_proto
*
cprot
=
lp
->
netdev
->
cprot
;
struct
concap_proto_ops
*
pops
=
cprot
?
cprot
->
pops
:
0
;
#endif
del_timer_sync
(
&
lp
->
hup_timer
);
if
(
lp
->
flags
&
ISDN_NET_CONNECTED
)
{
...
...
@@ -794,18 +706,10 @@ isdn_net_hangup(isdn_net_local *lp)
}
}
printk
(
KERN_INFO
"isdn_net: local hangup %s
\n
"
,
lp
->
name
);
#ifdef CONFIG_ISDN_PPP
if
(
lp
->
p_encap
==
ISDN_NET_ENCAP_SYNCPPP
)
isdn_ppp_free
(
lp
);
#endif
if
(
lp
->
disconnected
)
lp
->
disconnected
(
lp
);
isdn_net_lp_disconnected
(
lp
);
#ifdef CONFIG_ISDN_X25
/* try if there are generic encap protocol
receiver routines and signal the closure of
the link */
if
(
pops
&&
pops
->
disconn_ind
)
pops
->
disconn_ind
(
cprot
);
#endif
/* CONFIG_ISDN_X25 */
isdn_slot_command
(
lp
->
isdn_slot
,
ISDN_CMD_HANGUP
,
&
cmd
);
printk
(
KERN_INFO
"%s: Chargesum is %d
\n
"
,
lp
->
name
,
lp
->
charge
);
...
...
@@ -861,12 +765,10 @@ isdn_net_log_skb(struct sk_buff * skb, isdn_net_local * lp)
proto
=
ntohs
(
*
(
unsigned
short
*
)
&
buf
[
2
]);
p
=
&
buf
[
4
];
break
;
#ifdef CONFIG_ISDN_PPP
case
ISDN_NET_ENCAP_SYNCPPP
:
proto
=
ntohs
(
skb
->
protocol
);
p
=
&
buf
[
IPPP_MAX_HEADER
];
break
;
#endif
}
}
data_ofs
=
((
p
[
0
]
&
15
)
*
4
);
...
...
@@ -1025,11 +927,9 @@ isdn_net_xmit(struct net_device *ndev, struct sk_buff *skb)
}
/* For the other encaps the header has already been built */
#ifdef CONFIG_ISDN_PPP
if
(
lp
->
p_encap
==
ISDN_NET_ENCAP_SYNCPPP
)
{
return
isdn_ppp_xmit
(
skb
,
ndev
);
}
#endif
nd
=
((
isdn_net_local
*
)
ndev
->
priv
)
->
netdev
;
lp
=
isdn_net_get_locked_lp
(
nd
);
if
(
!
lp
)
{
...
...
@@ -1138,27 +1038,10 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
{
unsigned
long
flags
;
isdn_net_local
*
lp
=
(
isdn_net_local
*
)
ndev
->
priv
;
#ifdef CONFIG_ISDN_X25
struct
concap_proto
*
cprot
=
lp
->
netdev
->
cprot
;
#endif
#ifdef CONFIG_ISDN_X25
/* At this point hard_start_xmit() passes control to the encapsulation
protocol (if present).
For X.25 auto-dialing is completly bypassed because:
- It does not conform with the semantics of a reliable datalink
service as needed by X.25 PLP.
- I don't want that the interface starts dialing when the network layer
sends a message which requests to disconnect the lapb link (or if it
sends any other message not resulting in data transmission).
Instead, dialing will be initiated by the encapsulation protocol entity
when a dl_establish request is received from the upper layer.
*/
if
(
cprot
)
{
int
ret
=
cprot
->
pops
->
encap_and_xmit
(
cprot
,
skb
);
if
(
ret
)
netif_stop_queue
(
ndev
);
return
ret
;
}
else
#endif
if
(
lp
->
p_encap
==
ISDN_NET_ENCAP_X25IFACE
)
return
isdn_x25_start_xmit
(
skb
,
ndev
);
/* auto-dialing xmit function */
{
isdn_net_adjust_hdr
(
skb
,
ndev
);
...
...
@@ -1219,7 +1102,7 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
isdn_net_log_skb
(
skb
,
lp
);
/* Connect interface with channel */
isdn_net_bind_channel
(
lp
,
chi
);
#ifdef CONFIG_ISDN_PPP
if
(
lp
->
p_encap
==
ISDN_NET_ENCAP_SYNCPPP
)
{
/* no 'first_skb' handling for syncPPP */
if
(
isdn_ppp_bind
(
lp
)
<
0
)
{
...
...
@@ -1233,7 +1116,6 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
netif_stop_queue
(
ndev
);
return
1
;
/* let upper layer requeue skb packet */
}
#endif
/* Initiate dialing */
restore_flags
(
flags
);
init_dialout
(
lp
);
...
...
@@ -1262,25 +1144,13 @@ static int
isdn_net_close
(
struct
net_device
*
dev
)
{
struct
net_device
*
p
;
#ifdef CONFIG_ISDN_X25
struct
concap_proto
*
cprot
=
(
(
isdn_net_local
*
)
dev
->
priv
)
->
netdev
->
cprot
;
/* printk(KERN_DEBUG "isdn_net_close %s\n" , dev-> name ); */
#endif
#ifdef CONFIG_ISDN_X25
if
(
cprot
&&
cprot
->
pops
)
cprot
->
pops
->
close
(
cprot
);
#endif
isdn_x25_close
(
dev
);
netif_stop_queue
(
dev
);
if
((
p
=
(((
isdn_net_local
*
)
dev
->
priv
)
->
slave
)))
{
/* If this interface has slaves, stop them also */
while
(
p
)
{
#ifdef CONFIG_ISDN_X25
cprot
=
(
(
isdn_net_local
*
)
p
->
priv
)
->
netdev
->
cprot
;
if
(
cprot
&&
cprot
->
pops
)
cprot
->
pops
->
close
(
cprot
);
#endif
isdn_x25_close
(
p
);
isdn_net_hangup
(
p
->
priv
);
p
=
(((
isdn_net_local
*
)
p
->
priv
)
->
slave
);
}
...
...
@@ -1300,417 +1170,6 @@ isdn_net_get_stats(struct net_device *dev)
return
&
lp
->
stats
;
}
/* This is simply a copy from std. eth.c EXCEPT we pull ETH_HLEN
* instead of dev->hard_header_len off. This is done because the
* lowlevel-driver has already pulled off its stuff when we get
* here and this routine only gets called with p_encap == ETHER.
* Determine the packet's protocol ID. The rule here is that we
* assume 802.3 if the type field is short enough to be a length.
* This is normal practice and works for any 'now in use' protocol.
*/
static
unsigned
short
isdn_net_type_trans
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
)
{
struct
ethhdr
*
eth
;
unsigned
char
*
rawp
;
skb
->
mac
.
raw
=
skb
->
data
;
skb_pull
(
skb
,
ETH_HLEN
);
eth
=
skb
->
mac
.
ethernet
;
if
(
*
eth
->
h_dest
&
1
)
{
if
(
memcmp
(
eth
->
h_dest
,
dev
->
broadcast
,
ETH_ALEN
)
==
0
)
skb
->
pkt_type
=
PACKET_BROADCAST
;
else
skb
->
pkt_type
=
PACKET_MULTICAST
;
}
/*
* This ALLMULTI check should be redundant by 1.4
* so don't forget to remove it.
*/
else
if
(
dev
->
flags
&
(
IFF_PROMISC
/*| IFF_ALLMULTI*/
))
{
if
(
memcmp
(
eth
->
h_dest
,
dev
->
dev_addr
,
ETH_ALEN
))
skb
->
pkt_type
=
PACKET_OTHERHOST
;
}
if
(
ntohs
(
eth
->
h_proto
)
>=
1536
)
return
eth
->
h_proto
;
rawp
=
skb
->
data
;
/*
* This is a magic hack to spot IPX packets. Older Novell breaks
* the protocol design and runs IPX over 802.3 without an 802.2 LLC
* layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This
* won't work for fault tolerant netware but does for the rest.
*/
if
(
*
(
unsigned
short
*
)
rawp
==
0xFFFF
)
return
htons
(
ETH_P_802_3
);
/*
* Real 802.2 LLC
*/
return
htons
(
ETH_P_802_2
);
}
/*
* CISCO HDLC keepalive specific stuff
*/
static
struct
sk_buff
*
isdn_net_ciscohdlck_alloc_skb
(
isdn_net_local
*
lp
,
int
len
)
{
unsigned
short
hl
=
isdn_slot_hdrlen
(
lp
->
isdn_slot
);
struct
sk_buff
*
skb
;
skb
=
alloc_skb
(
hl
+
len
,
GFP_ATOMIC
);
if
(
!
skb
)
{
printk
(
"isdn out of mem at %s:%d!
\n
"
,
__FILE__
,
__LINE__
);
return
0
;
}
skb_reserve
(
skb
,
hl
);
return
skb
;
}
/* cisco hdlck device private ioctls */
int
isdn_ciscohdlck_dev_ioctl
(
struct
net_device
*
dev
,
struct
ifreq
*
ifr
,
int
cmd
)
{
isdn_net_local
*
lp
=
(
isdn_net_local
*
)
dev
->
priv
;
unsigned
long
len
=
0
;
unsigned
long
expires
=
0
;
int
tmp
=
0
;
int
period
=
lp
->
cisco_keepalive_period
;
char
debserint
=
lp
->
cisco_debserint
;
int
rc
=
0
;
if
(
lp
->
p_encap
!=
ISDN_NET_ENCAP_CISCOHDLCK
)
return
-
EINVAL
;
switch
(
cmd
)
{
/* get/set keepalive period */
case
SIOCGKEEPPERIOD
:
len
=
(
unsigned
long
)
sizeof
(
lp
->
cisco_keepalive_period
);
if
(
copy_to_user
((
char
*
)
ifr
->
ifr_ifru
.
ifru_data
,
(
int
*
)
&
lp
->
cisco_keepalive_period
,
len
))
rc
=
-
EFAULT
;
break
;
case
SIOCSKEEPPERIOD
:
tmp
=
lp
->
cisco_keepalive_period
;
len
=
(
unsigned
long
)
sizeof
(
lp
->
cisco_keepalive_period
);
if
(
copy_from_user
((
int
*
)
&
period
,
(
char
*
)
ifr
->
ifr_ifru
.
ifru_data
,
len
))
rc
=
-
EFAULT
;
if
((
period
>
0
)
&&
(
period
<=
32767
))
lp
->
cisco_keepalive_period
=
period
;
else
rc
=
-
EINVAL
;
if
(
!
rc
&&
(
tmp
!=
lp
->
cisco_keepalive_period
))
{
expires
=
(
unsigned
long
)(
jiffies
+
lp
->
cisco_keepalive_period
*
HZ
);
mod_timer
(
&
lp
->
cisco_timer
,
expires
);
printk
(
KERN_INFO
"%s: Keepalive period set "
"to %d seconds.
\n
"
,
lp
->
name
,
lp
->
cisco_keepalive_period
);
}
break
;
/* get/set debugging */
case
SIOCGDEBSERINT
:
len
=
(
unsigned
long
)
sizeof
(
lp
->
cisco_debserint
);
if
(
copy_to_user
((
char
*
)
ifr
->
ifr_ifru
.
ifru_data
,
(
char
*
)
&
lp
->
cisco_debserint
,
len
))
rc
=
-
EFAULT
;
break
;
case
SIOCSDEBSERINT
:
len
=
(
unsigned
long
)
sizeof
(
lp
->
cisco_debserint
);
if
(
copy_from_user
((
char
*
)
&
debserint
,
(
char
*
)
ifr
->
ifr_ifru
.
ifru_data
,
len
))
rc
=
-
EFAULT
;
if
((
debserint
>=
0
)
&&
(
debserint
<=
64
))
lp
->
cisco_debserint
=
debserint
;
else
rc
=
-
EINVAL
;
break
;
default:
rc
=
-
EINVAL
;
break
;
}
return
(
rc
);
}
/* called via cisco_timer.function */
static
void
isdn_net_ciscohdlck_slarp_send_keepalive
(
unsigned
long
data
)
{
isdn_net_local
*
lp
=
(
isdn_net_local
*
)
data
;
struct
sk_buff
*
skb
;
unsigned
char
*
p
;
unsigned
long
last_cisco_myseq
=
lp
->
cisco_myseq
;
int
myseq_diff
=
0
;
if
(
!
(
lp
->
flags
&
ISDN_NET_CONNECTED
)
||
lp
->
dialstate
!=
ST_ACTIVE
)
{
isdn_BUG
();
return
;
}
lp
->
cisco_myseq
++
;
myseq_diff
=
(
lp
->
cisco_myseq
-
lp
->
cisco_mineseen
);
if
((
lp
->
cisco_line_state
)
&&
((
myseq_diff
>=
3
)
||
(
myseq_diff
<=
-
3
)))
{
/* line up -> down */
lp
->
cisco_line_state
=
0
;
printk
(
KERN_WARNING
"UPDOWN: Line protocol on Interface %s,"
" changed state to down
\n
"
,
lp
->
name
);
/* should stop routing higher-level data accross */
}
else
if
((
!
lp
->
cisco_line_state
)
&&
(
myseq_diff
>=
0
)
&&
(
myseq_diff
<=
2
))
{
/* line down -> up */
lp
->
cisco_line_state
=
1
;
printk
(
KERN_WARNING
"UPDOWN: Line protocol on Interface %s,"
" changed state to up
\n
"
,
lp
->
name
);
/* restart routing higher-level data accross */
}
if
(
lp
->
cisco_debserint
)
printk
(
KERN_DEBUG
"%s: HDLC "
"myseq %lu, mineseen %lu%c, yourseen %lu, %s
\n
"
,
lp
->
name
,
last_cisco_myseq
,
lp
->
cisco_mineseen
,
((
last_cisco_myseq
==
lp
->
cisco_mineseen
)
?
'*'
:
040
),
lp
->
cisco_yourseq
,
((
lp
->
cisco_line_state
)
?
"line up"
:
"line down"
));
skb
=
isdn_net_ciscohdlck_alloc_skb
(
lp
,
4
+
14
);
if
(
!
skb
)
return
;
p
=
skb_put
(
skb
,
4
+
14
);
/* cisco header */
p
+=
put_u8
(
p
,
CISCO_ADDR_UNICAST
);
p
+=
put_u8
(
p
,
CISCO_CTRL
);
p
+=
put_u16
(
p
,
CISCO_TYPE_SLARP
);
/* slarp keepalive */
p
+=
put_u32
(
p
,
CISCO_SLARP_KEEPALIVE
);
p
+=
put_u32
(
p
,
lp
->
cisco_myseq
);
p
+=
put_u32
(
p
,
lp
->
cisco_yourseq
);
p
+=
put_u16
(
p
,
0xffff
);
// reliablity, always 0xffff
isdn_net_write_super
(
lp
,
skb
);
lp
->
cisco_timer
.
expires
=
jiffies
+
lp
->
cisco_keepalive_period
*
HZ
;
add_timer
(
&
lp
->
cisco_timer
);
}
static
void
isdn_net_ciscohdlck_slarp_send_request
(
isdn_net_local
*
lp
)
{
struct
sk_buff
*
skb
;
unsigned
char
*
p
;
skb
=
isdn_net_ciscohdlck_alloc_skb
(
lp
,
4
+
14
);
if
(
!
skb
)
return
;
p
=
skb_put
(
skb
,
4
+
14
);
/* cisco header */
p
+=
put_u8
(
p
,
CISCO_ADDR_UNICAST
);
p
+=
put_u8
(
p
,
CISCO_CTRL
);
p
+=
put_u16
(
p
,
CISCO_TYPE_SLARP
);
/* slarp request */
p
+=
put_u32
(
p
,
CISCO_SLARP_REQUEST
);
p
+=
put_u32
(
p
,
0
);
// address
p
+=
put_u32
(
p
,
0
);
// netmask
p
+=
put_u16
(
p
,
0
);
// unused
isdn_net_write_super
(
lp
,
skb
);
}
static
void
isdn_net_ciscohdlck_connected
(
isdn_net_local
*
lp
)
{
lp
->
cisco_myseq
=
0
;
lp
->
cisco_mineseen
=
0
;
lp
->
cisco_yourseq
=
0
;
lp
->
cisco_keepalive_period
=
ISDN_TIMER_KEEPINT
;
lp
->
cisco_last_slarp_in
=
0
;
lp
->
cisco_line_state
=
0
;
lp
->
cisco_debserint
=
0
;
/* send slarp request because interface/seq.no.s reset */
isdn_net_ciscohdlck_slarp_send_request
(
lp
);
init_timer
(
&
lp
->
cisco_timer
);
lp
->
cisco_timer
.
data
=
(
unsigned
long
)
lp
;
lp
->
cisco_timer
.
function
=
isdn_net_ciscohdlck_slarp_send_keepalive
;
lp
->
cisco_timer
.
expires
=
jiffies
+
lp
->
cisco_keepalive_period
*
HZ
;
add_timer
(
&
lp
->
cisco_timer
);
}
static
void
isdn_net_ciscohdlck_disconnected
(
isdn_net_local
*
lp
)
{
del_timer
(
&
lp
->
cisco_timer
);
}
static
void
isdn_net_ciscohdlck_slarp_send_reply
(
isdn_net_local
*
lp
)
{
struct
sk_buff
*
skb
;
unsigned
char
*
p
;
struct
in_device
*
in_dev
=
NULL
;
u32
addr
=
0
;
/* local ipv4 address */
u32
mask
=
0
;
/* local netmask */
if
((
in_dev
=
lp
->
netdev
->
dev
.
ip_ptr
)
!=
NULL
)
{
/* take primary(first) address of interface */
struct
in_ifaddr
*
ifa
=
in_dev
->
ifa_list
;
if
(
ifa
!=
NULL
)
{
addr
=
ifa
->
ifa_local
;
mask
=
ifa
->
ifa_mask
;
}
}
skb
=
isdn_net_ciscohdlck_alloc_skb
(
lp
,
4
+
14
);
if
(
!
skb
)
return
;
p
=
skb_put
(
skb
,
4
+
14
);
/* cisco header */
p
+=
put_u8
(
p
,
CISCO_ADDR_UNICAST
);
p
+=
put_u8
(
p
,
CISCO_CTRL
);
p
+=
put_u16
(
p
,
CISCO_TYPE_SLARP
);
/* slarp reply, send own ip/netmask; if values are nonsense remote
* should think we are unable to provide it with an address via SLARP */
p
+=
put_u32
(
p
,
CISCO_SLARP_REPLY
);
p
+=
put_u32
(
p
,
addr
);
// address
p
+=
put_u32
(
p
,
mask
);
// netmask
p
+=
put_u16
(
p
,
0
);
// unused
isdn_net_write_super
(
lp
,
skb
);
}
static
void
isdn_net_ciscohdlck_slarp_in
(
isdn_net_local
*
lp
,
struct
sk_buff
*
skb
)
{
unsigned
char
*
p
;
int
period
;
u32
code
;
u32
my_seq
,
addr
;
u32
your_seq
,
mask
;
u32
local
;
u16
unused
;
if
(
skb
->
len
<
14
)
return
;
p
=
skb
->
data
;
p
+=
get_u32
(
p
,
&
code
);
switch
(
code
)
{
case
CISCO_SLARP_REQUEST
:
lp
->
cisco_yourseq
=
0
;
isdn_net_ciscohdlck_slarp_send_reply
(
lp
);
break
;
case
CISCO_SLARP_REPLY
:
addr
=
ntohl
(
*
(
u32
*
)
p
);
mask
=
ntohl
(
*
(
u32
*
)(
p
+
4
));
if
(
mask
!=
0xfffffffc
)
goto
slarp_reply_out
;
if
((
addr
&
3
)
==
0
||
(
addr
&
3
)
==
3
)
goto
slarp_reply_out
;
local
=
addr
^
3
;
printk
(
KERN_INFO
"%s: got slarp reply: "
"remote ip: %d.%d.%d.%d, "
"local ip: %d.%d.%d.%d "
"mask: %d.%d.%d.%d
\n
"
,
lp
->
name
,
HIPQUAD
(
addr
),
HIPQUAD
(
local
),
HIPQUAD
(
mask
));
break
;
slarp_reply_out:
printk
(
KERN_INFO
"%s: got invalid slarp "
"reply (%d.%d.%d.%d/%d.%d.%d.%d) "
"- ignored
\n
"
,
lp
->
name
,
HIPQUAD
(
addr
),
HIPQUAD
(
mask
));
break
;
case
CISCO_SLARP_KEEPALIVE
:
period
=
(
int
)((
jiffies
-
lp
->
cisco_last_slarp_in
+
HZ
/
2
-
1
)
/
HZ
);
if
(
lp
->
cisco_debserint
&&
(
period
!=
lp
->
cisco_keepalive_period
)
&&
lp
->
cisco_last_slarp_in
)
{
printk
(
KERN_DEBUG
"%s: Keepalive period mismatch - "
"is %d but should be %d.
\n
"
,
lp
->
name
,
period
,
lp
->
cisco_keepalive_period
);
}
lp
->
cisco_last_slarp_in
=
jiffies
;
p
+=
get_u32
(
p
,
&
my_seq
);
p
+=
get_u32
(
p
,
&
your_seq
);
p
+=
get_u16
(
p
,
&
unused
);
lp
->
cisco_yourseq
=
my_seq
;
lp
->
cisco_mineseen
=
your_seq
;
break
;
}
}
static
void
isdn_net_ciscohdlck_receive
(
isdn_net_local
*
lp
,
struct
sk_buff
*
skb
)
{
unsigned
char
*
p
;
u8
addr
;
u8
ctrl
;
u16
type
;
if
(
skb
->
len
<
4
)
goto
out_free
;
p
=
skb
->
data
;
p
+=
get_u8
(
p
,
&
addr
);
p
+=
get_u8
(
p
,
&
ctrl
);
p
+=
get_u16
(
p
,
&
type
);
skb_pull
(
skb
,
4
);
if
(
addr
!=
CISCO_ADDR_UNICAST
&&
addr
!=
CISCO_ADDR_BROADCAST
)
{
printk
(
KERN_WARNING
"%s: Unknown Cisco addr 0x%02x
\n
"
,
lp
->
name
,
addr
);
goto
out_free
;
}
if
(
ctrl
!=
CISCO_CTRL
)
{
printk
(
KERN_WARNING
"%s: Unknown Cisco ctrl 0x%02x
\n
"
,
lp
->
name
,
ctrl
);
goto
out_free
;
}
switch
(
type
)
{
case
CISCO_TYPE_SLARP
:
isdn_net_ciscohdlck_slarp_in
(
lp
,
skb
);
goto
out_free
;
case
CISCO_TYPE_CDP
:
if
(
lp
->
cisco_debserint
)
printk
(
KERN_DEBUG
"%s: Received CDP packet. use "
"
\"
no cdp enable
\"
on cisco.
\n
"
,
lp
->
name
);
goto
out_free
;
default:
/* no special cisco protocol */
skb
->
protocol
=
htons
(
type
);
netif_rx
(
skb
);
return
;
}
out_free:
kfree_skb
(
skb
);
}
/*
* Got a packet from ISDN-Channel.
*/
...
...
@@ -1719,12 +1178,7 @@ isdn_net_receive(struct net_device *ndev, struct sk_buff *skb)
{
isdn_net_local
*
lp
=
(
isdn_net_local
*
)
ndev
->
priv
;
isdn_net_local
*
olp
=
lp
;
/* original 'lp' */
#ifdef CONFIG_ISDN_PPP
int
proto
=
PPP_PROTOCOL
(
skb
->
data
);
#endif
#ifdef CONFIG_ISDN_X25
struct
concap_proto
*
cprot
=
lp
->
netdev
->
cprot
;
#endif
lp
->
transcount
+=
skb
->
len
;
lp
->
stats
.
rx_packets
++
;
...
...
@@ -1742,72 +1196,8 @@ isdn_net_receive(struct net_device *ndev, struct sk_buff *skb)
skb
->
pkt_type
=
PACKET_HOST
;
skb
->
mac
.
raw
=
skb
->
data
;
isdn_dumppkt
(
"R:"
,
skb
->
data
,
skb
->
len
,
40
);
switch
(
lp
->
p_encap
)
{
case
ISDN_NET_ENCAP_ETHER
:
/* Ethernet over ISDN */
olp
->
huptimer
=
0
;
lp
->
huptimer
=
0
;
skb
->
protocol
=
isdn_net_type_trans
(
skb
,
ndev
);
break
;
case
ISDN_NET_ENCAP_UIHDLC
:
/* HDLC with UI-frame (for ispa with -h1 option) */
olp
->
huptimer
=
0
;
lp
->
huptimer
=
0
;
skb_pull
(
skb
,
2
);
/* Fall through */
case
ISDN_NET_ENCAP_RAWIP
:
/* RAW-IP without MAC-Header */
olp
->
huptimer
=
0
;
lp
->
huptimer
=
0
;
skb
->
protocol
=
htons
(
ETH_P_IP
);
break
;
case
ISDN_NET_ENCAP_CISCOHDLCK
:
isdn_net_ciscohdlck_receive
(
lp
,
skb
);
return
;
case
ISDN_NET_ENCAP_CISCOHDLC
:
/* CISCO-HDLC IP with type field and fake I-frame-header */
skb_pull
(
skb
,
2
);
/* Fall through */
case
ISDN_NET_ENCAP_IPTYP
:
/* IP with type field */
olp
->
huptimer
=
0
;
lp
->
huptimer
=
0
;
skb
->
protocol
=
*
(
unsigned
short
*
)
&
(
skb
->
data
[
0
]);
skb_pull
(
skb
,
2
);
if
(
*
(
unsigned
short
*
)
skb
->
data
==
0xFFFF
)
skb
->
protocol
=
htons
(
ETH_P_802_3
);
break
;
#ifdef CONFIG_ISDN_PPP
case
ISDN_NET_ENCAP_SYNCPPP
:
/*
* If encapsulation is syncppp, don't reset
* huptimer on LCP packets.
*/
if
(
proto
!=
PPP_LCP
)
{
olp
->
huptimer
=
0
;
lp
->
huptimer
=
0
;
}
isdn_ppp_receive
(
lp
->
netdev
,
olp
,
skb
);
return
;
#endif
default:
#ifdef CONFIG_ISDN_X25
/* try if there are generic sync_device receiver routines */
if
(
cprot
)
if
(
cprot
->
pops
)
if
(
cprot
->
pops
->
data_ind
){
cprot
->
pops
->
data_ind
(
cprot
,
skb
);
return
;
};
#endif
/* CONFIG_ISDN_X25 */
printk
(
KERN_WARNING
"%s: unknown encapsulation, dropping
\n
"
,
lp
->
name
);
kfree_skb
(
skb
);
return
;
}
netif_rx
(
skb
);
return
;
lp
->
receive
(
lp
->
netdev
,
olp
,
skb
);
}
/*
...
...
@@ -1831,120 +1221,20 @@ isdn_net_rcv_skb(int idx, struct sk_buff *skb)
return
0
;
}
/* We don't need to send arp, because we have point-to-point connections. */
static
int
my_eth_header
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
,
unsigned
short
type
,
void
*
daddr
,
void
*
saddr
,
unsigned
len
)
isdn_net_rebuild_header
(
struct
sk_buff
*
skb
)
{
struct
ethhdr
*
eth
=
(
struct
ethhdr
*
)
skb_push
(
skb
,
ETH_HLEN
);
/*
* Set the protocol type. For a packet of type ETH_P_802_3 we
* put the length here instead. It is up to the 802.2 layer to
* carry protocol information.
*/
if
(
type
!=
ETH_P_802_3
)
eth
->
h_proto
=
htons
(
type
);
else
eth
->
h_proto
=
htons
(
len
);
/*
* Set the source hardware address.
*/
if
(
saddr
)
memcpy
(
eth
->
h_source
,
saddr
,
dev
->
addr_len
);
else
memcpy
(
eth
->
h_source
,
dev
->
dev_addr
,
dev
->
addr_len
);
struct
net_device
*
dev
=
skb
->
dev
;
isdn_net_local
*
lp
=
dev
->
priv
;
int
ret
=
0
;
/*
* Anyway, the loopback-device should never use this function...
*/
if
(
lp
->
p_encap
==
ISDN_NET_ENCAP_ETHER
)
{
struct
ethhdr
*
eth
=
(
struct
ethhdr
*
)
skb
->
data
;
if
(
dev
->
flags
&
(
IFF_LOOPBACK
|
IFF_NOARP
))
{
memset
(
eth
->
h_dest
,
0
,
dev
->
addr_len
);
return
ETH_HLEN
/*(dev->hard_header_len)*/
;
}
if
(
daddr
)
{
memcpy
(
eth
->
h_dest
,
daddr
,
dev
->
addr_len
);
return
ETH_HLEN
/*dev->hard_header_len*/
;
}
return
-
ETH_HLEN
/*dev->hard_header_len*/
;
}
/*
* build an header
* depends on encaps that is being used.
*/
static
int
isdn_net_header
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
,
unsigned
short
type
,
void
*
daddr
,
void
*
saddr
,
unsigned
plen
)
{
isdn_net_local
*
lp
=
dev
->
priv
;
unsigned
char
*
p
;
ushort
len
=
0
;
switch
(
lp
->
p_encap
)
{
case
ISDN_NET_ENCAP_ETHER
:
len
=
my_eth_header
(
skb
,
dev
,
type
,
daddr
,
saddr
,
plen
);
break
;
#ifdef CONFIG_ISDN_PPP
case
ISDN_NET_ENCAP_SYNCPPP
:
/* stick on a fake header to keep fragmentation code happy. */
len
=
IPPP_MAX_HEADER
;
skb_push
(
skb
,
len
);
break
;
#endif
case
ISDN_NET_ENCAP_RAWIP
:
printk
(
KERN_WARNING
"isdn_net_header called with RAW_IP!
\n
"
);
len
=
0
;
break
;
case
ISDN_NET_ENCAP_IPTYP
:
/* ethernet type field */
*
((
ushort
*
)
skb_push
(
skb
,
2
))
=
htons
(
type
);
len
=
2
;
break
;
case
ISDN_NET_ENCAP_UIHDLC
:
/* HDLC with UI-Frames (for ispa with -h1 option) */
*
((
ushort
*
)
skb_push
(
skb
,
2
))
=
htons
(
0x0103
);
len
=
2
;
break
;
case
ISDN_NET_ENCAP_CISCOHDLC
:
case
ISDN_NET_ENCAP_CISCOHDLCK
:
p
=
skb_push
(
skb
,
4
);
p
+=
put_u8
(
p
,
CISCO_ADDR_UNICAST
);
p
+=
put_u8
(
p
,
CISCO_CTRL
);
p
+=
put_u16
(
p
,
type
);
len
=
4
;
break
;
#ifdef CONFIG_ISDN_X25
default:
/* try if there are generic concap protocol routines */
if
(
lp
->
netdev
->
cprot
){
printk
(
KERN_WARNING
"isdn_net_header called with concap_proto!
\n
"
);
len
=
0
;
break
;
}
break
;
#endif
/* CONFIG_ISDN_X25 */
}
return
len
;
}
/* We don't need to send arp, because we have point-to-point connections. */
static
int
isdn_net_rebuild_header
(
struct
sk_buff
*
skb
)
{
struct
net_device
*
dev
=
skb
->
dev
;
isdn_net_local
*
lp
=
dev
->
priv
;
int
ret
=
0
;
if
(
lp
->
p_encap
==
ISDN_NET_ENCAP_ETHER
)
{
struct
ethhdr
*
eth
=
(
struct
ethhdr
*
)
skb
->
data
;
/*
* Only ARP/IP is currently supported
*/
/*
* Only ARP/IP is currently supported
*/
if
(
eth
->
h_proto
!=
htons
(
ETH_P_IP
))
{
printk
(
KERN_WARNING
...
...
@@ -1970,12 +1260,9 @@ static int
isdn_net_init
(
struct
net_device
*
ndev
)
{
ushort
max_hlhdr_len
=
0
;
isdn_net_local
*
lp
=
(
isdn_net_local
*
)
ndev
->
priv
;
int
drvidx
,
i
;
ether_setup
(
ndev
);
lp
->
org_hhc
=
ndev
->
hard_header_cache
;
lp
->
org_hcu
=
ndev
->
header_cache_update
;
/* Setup the generic properties */
...
...
@@ -2312,14 +1599,13 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
lp
->
dialstate
=
ST_WAIT_BEFORE_CB
;
/* Connect interface with channel */
isdn_net_bind_channel
(
lp
,
chi
);
#ifdef CONFIG_ISDN_PPP
if
(
lp
->
p_encap
==
ISDN_NET_ENCAP_SYNCPPP
)
if
(
isdn_ppp_bind
(
lp
)
<
0
)
{
isdn_net_unbind_channel
(
lp
);
restore_flags
(
flags
);
return
0
;
}
#endif
/* Initiate dialing by returning 2 or 4 */
restore_flags
(
flags
);
return
(
lp
->
flags
&
ISDN_NET_CBHUP
)
?
2
:
4
;
...
...
@@ -2329,10 +1615,9 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
/* if this interface is dialing, it does it probably on a different
device, so free this device */
if
(
lp
->
dialstate
==
ST_OUT_WAIT_DCONN
)
{
#ifdef CONFIG_ISDN_PPP
if
(
lp
->
p_encap
==
ISDN_NET_ENCAP_SYNCPPP
)
isdn_ppp_free
(
lp
);
#endif
if
(
lp
->
disconnected
)
lp
->
disconnected
(
lp
);
isdn_net_lp_disconnected
(
lp
);
isdn_slot_free
(
lp
->
isdn_slot
,
ISDN_USAGE_NET
);
...
...
@@ -2360,14 +1645,12 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
add_timer
(
&
lp
->
dial_timer
);
lp
->
dialstate
=
ST_IN_WAIT_DCONN
;
#ifdef CONFIG_ISDN_PPP
if
(
lp
->
p_encap
==
ISDN_NET_ENCAP_SYNCPPP
)
if
(
isdn_ppp_bind
(
lp
)
<
0
)
{
isdn_net_unbind_channel
(
lp
);
restore_flags
(
flags
);
return
0
;
}
#endif
restore_flags
(
flags
);
return
1
;
}
...
...
@@ -2423,14 +1706,12 @@ isdn_net_force_dial_lp(isdn_net_local * lp)
}
/* Connect interface with channel */
isdn_net_bind_channel
(
lp
,
chi
);
#ifdef CONFIG_ISDN_PPP
if
(
lp
->
p_encap
==
ISDN_NET_ENCAP_SYNCPPP
)
if
(
isdn_ppp_bind
(
lp
)
<
0
)
{
isdn_net_unbind_channel
(
lp
);
restore_flags
(
flags
);
return
-
EAGAIN
;
}
#endif
/* Initiate dialing */
restore_flags
(
flags
);
init_dialout
(
lp
);
...
...
@@ -2533,7 +1814,7 @@ isdn_net_new(char *name, struct net_device *master)
netdev
->
local
.
isdn_slot
=
-
1
;
netdev
->
local
.
pre_device
=
-
1
;
netdev
->
local
.
pre_channel
=
-
1
;
netdev
->
local
.
exclusive
=
-
1
;
netdev
->
local
.
exclusive
=
0
;
netdev
->
local
.
ppp_slot
=
-
1
;
netdev
->
local
.
pppbind
=
-
1
;
skb_queue_head_init
(
&
netdev
->
local
.
super_tx_queue
);
...
...
@@ -2591,6 +1872,136 @@ isdn_net_newslave(char *parm)
return
isdn_net_new
(
p
+
1
,
&
m
->
dev
);
}
static
int
isdn_net_set_encap
(
isdn_net_dev
*
p
,
isdn_net_ioctl_cfg
*
cfg
)
{
isdn_net_local
*
lp
=
&
p
->
local
;
int
retval
;
if
(
lp
->
p_encap
==
cfg
->
p_encap
){
/* nothing to do */
retval
=
0
;
goto
out
;
}
if
(
isdn_net_device_started
(
p
))
{
retval
=
-
EBUSY
;
goto
out
;
}
switch
(
lp
->
p_encap
)
{
case
ISDN_NET_ENCAP_X25IFACE
:
isdn_x25_cleanup
(
p
);
break
;
}
lp
->
p_encap
=
cfg
->
p_encap
;
switch
(
lp
->
p_encap
)
{
case
ISDN_NET_ENCAP_SYNCPPP
:
retval
=
isdn_ppp_setup
(
p
);
break
;
case
ISDN_NET_ENCAP_X25IFACE
:
retval
=
isdn_x25_setup
(
p
,
cfg
->
p_encap
);
break
;
case
ISDN_NET_ENCAP_CISCOHDLC
:
case
ISDN_NET_ENCAP_CISCOHDLCK
:
retval
=
isdn_ciscohdlck_setup
(
p
);
break
;
case
ISDN_NET_ENCAP_RAWIP
:
retval
=
isdn_rawip_setup
(
p
);
break
;
case
ISDN_NET_ENCAP_ETHER
:
retval
=
isdn_ether_setup
(
p
);
break
;
case
ISDN_NET_ENCAP_UIHDLC
:
retval
=
isdn_uihdlc_setup
(
p
);
break
;
case
ISDN_NET_ENCAP_IPTYP
:
retval
=
isdn_iptyp_setup
(
p
);
break
;
default:
retval
=
-
EINVAL
;
break
;
}
if
(
retval
!=
0
)
lp
->
p_encap
=
-
1
;
out:
return
retval
;
}
static
int
isdn_net_bind
(
isdn_net_dev
*
p
,
isdn_net_ioctl_cfg
*
cfg
)
{
isdn_net_local
*
lp
=
&
p
->
local
;
int
i
,
retval
;
int
drvidx
=
-
1
;
int
chidx
=
-
1
;
char
drvid
[
25
];
strncpy
(
drvid
,
cfg
->
drvid
,
24
);
drvid
[
24
]
=
0
;
if
(
cfg
->
exclusive
&&
!
strlen
(
drvid
))
{
/* If we want to bind exclusively, need to specify drv/chan */
retval
=
-
ENODEV
;
goto
out
;
}
if
(
strlen
(
drvid
))
{
/* A bind has been requested ... */
char
*
c
=
strchr
(
drvid
,
','
);
if
(
!
c
)
{
retval
=
-
ENODEV
;
goto
out
;
}
/* The channel-number is appended to the driver-Id with a comma */
*
c
=
0
;
chidx
=
simple_strtol
(
c
+
1
,
NULL
,
10
);
for
(
i
=
0
;
i
<
ISDN_MAX_DRIVERS
;
i
++
)
{
/* Lookup driver-Id in array */
if
(
!
strcmp
(
dev
->
drvid
[
i
],
drvid
))
{
drvidx
=
i
;
break
;
}
}
if
(
drvidx
==
-
1
||
chidx
==
-
1
)
{
/* Either driver-Id or channel-number invalid */
retval
=
-
ENODEV
;
goto
out
;
}
}
if
(
cfg
->
exclusive
==
lp
->
exclusive
&&
drvidx
==
lp
->
pre_device
&&
chidx
==
lp
->
pre_channel
)
{
/* no change */
retval
=
0
;
goto
out
;
}
if
(
lp
->
exclusive
)
{
isdn_unexclusive_channel
(
lp
->
pre_device
,
lp
->
pre_channel
);
isdn_free_channel
(
lp
->
pre_device
,
lp
->
pre_channel
,
ISDN_USAGE_NET
);
lp
->
exclusive
=
0
;
}
if
(
cfg
->
exclusive
)
{
/* If binding is exclusive, try to grab the channel */
i
=
isdn_get_free_slot
(
ISDN_USAGE_NET
,
lp
->
l2_proto
,
lp
->
l3_proto
,
drvidx
,
chidx
,
cfg
->
eaz
);
printk
(
"i %d
\n
"
,
i
);
if
(
i
<
0
)
{
/* Grab failed, because desired channel is in use */
retval
=
-
EBUSY
;
goto
out
;
}
/* All went ok, so update isdninfo */
isdn_slot_set_usage
(
i
,
ISDN_USAGE_EXCLUSIVE
);
lp
->
exclusive
=
1
;
}
lp
->
pre_device
=
drvidx
;
lp
->
pre_channel
=
chidx
;
retval
=
0
;
out:
return
retval
;
}
/*
* Set interface-parameters.
* Always set all parameters, so the user-level application is responsible
...
...
@@ -2598,237 +2009,102 @@ isdn_net_newslave(char *parm)
* setup first, if only selected parameters are to be changed.
*/
int
isdn_net_setcfg
(
isdn_net_ioctl_cfg
*
cfg
)
isdn_net_setcfg
(
isdn_net_ioctl_cfg
*
cfg
)
{
isdn_net_dev
*
p
=
isdn_net_findif
(
cfg
->
name
);
isdn_net_local
*
lp
=
&
p
->
local
;
ulong
features
;
int
i
;
int
drvidx
;
int
chidx
;
char
drvid
[
25
];
#ifdef CONFIG_ISDN_X25
ulong
flags
;
#endif
if
(
p
)
{
isdn_net_local
*
lp
=
&
p
->
local
;
int
i
,
retval
;
/* See if any registered driver supports the features we want */
features
=
((
1
<<
cfg
->
l2_proto
)
<<
ISDN_FEATURE_L2_SHIFT
)
|
((
1
<<
cfg
->
l3_proto
)
<<
ISDN_FEATURE_L3_SHIFT
);
for
(
i
=
0
;
i
<
ISDN_MAX_DRIVERS
;
i
++
)
if
(
dev
->
drv
[
i
])
if
((
dev
->
drv
[
i
]
->
interface
->
features
&
features
)
==
features
)
break
;
if
(
i
==
ISDN_MAX_DRIVERS
)
{
printk
(
KERN_WARNING
"isdn_net: No driver with selected features
\n
"
);
return
-
ENODEV
;
}
if
(
lp
->
p_encap
!=
cfg
->
p_encap
){
#ifdef CONFIG_ISDN_X25
struct
concap_proto
*
cprot
=
p
->
cprot
;
#endif
if
(
isdn_net_device_started
(
p
))
{
printk
(
KERN_WARNING
"%s: cannot change encap when if is up
\n
"
,
lp
->
name
);
return
-
EBUSY
;
}
#ifdef CONFIG_ISDN_X25
/* delete old encapsulation protocol if present ... */
save_flags
(
flags
);
cli
();
/* avoid races with incoming events trying to
call cprot->pops methods */
if
(
cprot
&&
cprot
->
pops
)
cprot
->
pops
->
proto_del
(
cprot
);
p
->
cprot
=
NULL
;
lp
->
dops
=
NULL
;
restore_flags
(
flags
);
/* ... , prepare for configuration of new one ... */
switch
(
cfg
->
p_encap
){
case
ISDN_NET_ENCAP_X25IFACE
:
lp
->
dops
=
&
isdn_concap_reliable_dl_dops
;
}
/* ... and allocate new one ... */
p
->
cprot
=
isdn_concap_new
(
cfg
->
p_encap
);
/* p -> cprot == NULL now if p_encap is not supported
by means of the concap_proto mechanism */
/* the protocol is not configured yet; this will
happen later when isdn_net_reset() is called */
#endif
}
switch
(
cfg
->
p_encap
)
{
case
ISDN_NET_ENCAP_SYNCPPP
:
#ifndef CONFIG_ISDN_PPP
printk
(
KERN_WARNING
"%s: SyncPPP support not configured
\n
"
,
lp
->
name
);
return
-
EINVAL
;
#else
p
->
dev
.
type
=
ARPHRD_PPP
;
/* change ARP type */
p
->
dev
.
addr_len
=
0
;
p
->
dev
.
do_ioctl
=
isdn_ppp_dev_ioctl
;
#endif
break
;
case
ISDN_NET_ENCAP_X25IFACE
:
#ifndef CONFIG_ISDN_X25
printk
(
KERN_WARNING
"%s: isdn-x25 support not configured
\n
"
,
p
->
local
.
name
);
return
-
EINVAL
;
#else
p
->
dev
.
type
=
ARPHRD_X25
;
/* change ARP type */
p
->
dev
.
addr_len
=
0
;
#endif
break
;
case
ISDN_NET_ENCAP_CISCOHDLCK
:
p
->
dev
.
do_ioctl
=
isdn_ciscohdlck_dev_ioctl
;
break
;
default:
if
(
cfg
->
p_encap
>=
0
&&
cfg
->
p_encap
<=
ISDN_NET_ENCAP_MAX_ENCAP
)
if
(
!
p
)
{
retval
=
-
ENODEV
;
goto
out
;
}
/* See if any registered driver supports the features we want */
features
=
((
1
<<
cfg
->
l2_proto
)
<<
ISDN_FEATURE_L2_SHIFT
)
|
((
1
<<
cfg
->
l3_proto
)
<<
ISDN_FEATURE_L3_SHIFT
);
for
(
i
=
0
;
i
<
ISDN_MAX_DRIVERS
;
i
++
)
if
(
dev
->
drv
[
i
]
&&
(
dev
->
drv
[
i
]
->
interface
->
features
&
features
)
==
features
)
break
;
printk
(
KERN_WARNING
"%s: encapsulation protocol %d not supported
\n
"
,
p
->
local
.
name
,
cfg
->
p_encap
);
return
-
EINVAL
;
}
if
(
strlen
(
cfg
->
drvid
))
{
/* A bind has been requested ... */
char
*
c
,
*
e
;
drvidx
=
-
1
;
chidx
=
-
1
;
strcpy
(
drvid
,
cfg
->
drvid
);
if
((
c
=
strchr
(
drvid
,
','
)))
{
/* The channel-number is appended to the driver-Id with a comma */
chidx
=
(
int
)
simple_strtoul
(
c
+
1
,
&
e
,
10
);
if
(
e
==
c
)
chidx
=
-
1
;
*
c
=
'\0'
;
}
for
(
i
=
0
;
i
<
ISDN_MAX_DRIVERS
;
i
++
)
/* Lookup driver-Id in array */
if
(
!
(
strcmp
(
dev
->
drvid
[
i
],
drvid
)))
{
drvidx
=
i
;
break
;
}
if
((
drvidx
==
-
1
)
||
(
chidx
==
-
1
))
/* Either driver-Id or channel-number invalid */
return
-
ENODEV
;
}
else
{
/* Parameters are valid, so get them */
drvidx
=
lp
->
pre_device
;
chidx
=
lp
->
pre_channel
;
}
if
(
cfg
->
exclusive
>
0
)
{
unsigned
long
flags
;
/* If binding is exclusive, try to grab the channel */
save_flags
(
flags
);
if
((
i
=
isdn_get_free_slot
(
ISDN_USAGE_NET
,
lp
->
l2_proto
,
lp
->
l3_proto
,
drvidx
,
chidx
,
lp
->
msn
))
<
0
)
{
/* Grab failed, because desired channel is in use */
lp
->
exclusive
=
-
1
;
restore_flags
(
flags
);
return
-
EBUSY
;
}
/* All went ok, so update isdninfo */
isdn_slot_set_usage
(
i
,
ISDN_USAGE_EXCLUSIVE
);
restore_flags
(
flags
);
lp
->
exclusive
=
i
;
}
else
{
/* Non-exclusive binding or unbind. */
lp
->
exclusive
=
-
1
;
if
((
lp
->
pre_device
!=
-
1
)
&&
(
cfg
->
exclusive
==
-
1
))
{
isdn_unexclusive_channel
(
lp
->
pre_device
,
lp
->
pre_channel
);
isdn_free_channel
(
lp
->
pre_device
,
lp
->
pre_channel
,
ISDN_USAGE_NET
);
drvidx
=
-
1
;
chidx
=
-
1
;
}
}
strcpy
(
lp
->
msn
,
cfg
->
eaz
);
lp
->
pre_device
=
drvidx
;
lp
->
pre_channel
=
chidx
;
lp
->
onhtime
=
cfg
->
onhtime
;
lp
->
charge
=
cfg
->
charge
;
lp
->
l2_proto
=
cfg
->
l2_proto
;
lp
->
l3_proto
=
cfg
->
l3_proto
;
lp
->
cbdelay
=
cfg
->
cbdelay
*
HZ
/
5
;
lp
->
dialmax
=
cfg
->
dialmax
;
lp
->
triggercps
=
cfg
->
triggercps
;
lp
->
slavedelay
=
cfg
->
slavedelay
*
HZ
;
lp
->
pppbind
=
cfg
->
pppbind
;
lp
->
dialtimeout
=
cfg
->
dialtimeout
>=
0
?
cfg
->
dialtimeout
*
HZ
:
-
1
;
lp
->
dialwait
=
cfg
->
dialwait
*
HZ
;
if
(
cfg
->
secure
)
lp
->
flags
|=
ISDN_NET_SECURE
;
else
lp
->
flags
&=
~
ISDN_NET_SECURE
;
if
(
cfg
->
cbhup
)
lp
->
flags
|=
ISDN_NET_CBHUP
;
else
lp
->
flags
&=
~
ISDN_NET_CBHUP
;
switch
(
cfg
->
callback
)
{
case
0
:
lp
->
flags
&=
~
(
ISDN_NET_CALLBACK
|
ISDN_NET_CBOUT
);
break
;
case
1
:
lp
->
flags
|=
ISDN_NET_CALLBACK
;
lp
->
flags
&=
~
ISDN_NET_CBOUT
;
break
;
case
2
:
lp
->
flags
|=
ISDN_NET_CBOUT
;
lp
->
flags
&=
~
ISDN_NET_CALLBACK
;
break
;
}
lp
->
flags
&=
~
ISDN_NET_DIALMODE_MASK
;
/* first all bits off */
if
(
cfg
->
dialmode
&&
!
(
cfg
->
dialmode
&
ISDN_NET_DIALMODE_MASK
))
{
/* old isdnctrl version, where only 0 or 1 is given */
printk
(
KERN_WARNING
"Old isdnctrl version detected! Please update.
\n
"
);
lp
->
flags
|=
ISDN_NET_DM_OFF
;
/* turn on `off' bit */
}
else
{
lp
->
flags
|=
cfg
->
dialmode
;
/* turn on selected bits */
}
if
(
lp
->
flags
&
ISDN_NET_DM_OFF
)
isdn_net_hangup
(
lp
);
if
(
i
==
ISDN_MAX_DRIVERS
)
{
printk
(
KERN_WARNING
"isdn_net: No driver with selected features
\n
"
);
retval
=
-
ENODEV
;
goto
out
;
}
retval
=
isdn_net_set_encap
(
p
,
cfg
);
if
(
retval
)
goto
out
;
retval
=
isdn_net_bind
(
p
,
cfg
);
if
(
retval
)
goto
out
;
strncpy
(
lp
->
msn
,
cfg
->
eaz
,
ISDN_MSNLEN
-
1
);
lp
->
msn
[
ISDN_MSNLEN
-
1
]
=
0
;
lp
->
onhtime
=
cfg
->
onhtime
;
lp
->
charge
=
cfg
->
charge
;
lp
->
l2_proto
=
cfg
->
l2_proto
;
lp
->
l3_proto
=
cfg
->
l3_proto
;
lp
->
cbdelay
=
cfg
->
cbdelay
*
HZ
/
5
;
lp
->
dialmax
=
cfg
->
dialmax
;
lp
->
triggercps
=
cfg
->
triggercps
;
lp
->
slavedelay
=
cfg
->
slavedelay
*
HZ
;
lp
->
pppbind
=
cfg
->
pppbind
;
lp
->
dialtimeout
=
cfg
->
dialtimeout
>=
0
?
cfg
->
dialtimeout
*
HZ
:
-
1
;
lp
->
dialwait
=
cfg
->
dialwait
*
HZ
;
if
(
cfg
->
secure
)
lp
->
flags
|=
ISDN_NET_SECURE
;
else
lp
->
flags
&=
~
ISDN_NET_SECURE
;
if
(
cfg
->
cbhup
)
lp
->
flags
|=
ISDN_NET_CBHUP
;
else
lp
->
flags
&=
~
ISDN_NET_CBHUP
;
switch
(
cfg
->
callback
)
{
case
0
:
lp
->
flags
&=
~
(
ISDN_NET_CALLBACK
|
ISDN_NET_CBOUT
);
break
;
case
1
:
lp
->
flags
|=
ISDN_NET_CALLBACK
;
lp
->
flags
&=
~
ISDN_NET_CBOUT
;
break
;
case
2
:
lp
->
flags
|=
ISDN_NET_CBOUT
;
lp
->
flags
&=
~
ISDN_NET_CALLBACK
;
break
;
}
lp
->
flags
&=
~
ISDN_NET_DIALMODE_MASK
;
/* first all bits off */
if
(
cfg
->
dialmode
&&
!
(
cfg
->
dialmode
&
ISDN_NET_DIALMODE_MASK
))
{
retval
=
-
EINVAL
;
goto
out
;
}
if
(
cfg
->
chargehup
)
lp
->
hupflags
|=
ISDN_CHARGEHUP
;
else
lp
->
hupflags
&=
~
ISDN_CHARGEHUP
;
if
(
cfg
->
ihup
)
lp
->
hupflags
|=
ISDN_INHUP
;
else
lp
->
hupflags
&=
~
ISDN_INHUP
;
if
(
cfg
->
chargeint
>
10
)
{
lp
->
chargeint
=
cfg
->
chargeint
*
HZ
;
lp
->
charge_state
=
ST_CHARGE_HAVE_CINT
;
lp
->
hupflags
|=
ISDN_MANCHARGE
;
}
if
(
cfg
->
p_encap
!=
lp
->
p_encap
)
{
if
(
cfg
->
p_encap
==
ISDN_NET_ENCAP_RAWIP
)
{
p
->
dev
.
hard_header
=
NULL
;
p
->
dev
.
hard_header_cache
=
NULL
;
p
->
dev
.
header_cache_update
=
NULL
;
p
->
dev
.
flags
=
IFF_NOARP
|
IFF_POINTOPOINT
;
}
else
{
p
->
dev
.
hard_header
=
isdn_net_header
;
if
(
cfg
->
p_encap
==
ISDN_NET_ENCAP_ETHER
)
{
p
->
dev
.
hard_header_cache
=
lp
->
org_hhc
;
p
->
dev
.
header_cache_update
=
lp
->
org_hcu
;
p
->
dev
.
flags
=
IFF_BROADCAST
|
IFF_MULTICAST
;
}
else
{
p
->
dev
.
hard_header_cache
=
NULL
;
p
->
dev
.
header_cache_update
=
NULL
;
p
->
dev
.
flags
=
IFF_NOARP
|
IFF_POINTOPOINT
;
}
}
}
lp
->
p_encap
=
cfg
->
p_encap
;
return
0
;
lp
->
flags
|=
cfg
->
dialmode
;
/* turn on selected bits */
if
(
lp
->
flags
&
ISDN_NET_DM_OFF
)
isdn_net_hangup
(
lp
);
if
(
cfg
->
chargehup
)
lp
->
hupflags
|=
ISDN_CHARGEHUP
;
else
lp
->
hupflags
&=
~
ISDN_CHARGEHUP
;
if
(
cfg
->
ihup
)
lp
->
hupflags
|=
ISDN_INHUP
;
else
lp
->
hupflags
&=
~
ISDN_INHUP
;
if
(
cfg
->
chargeint
>
10
)
{
lp
->
chargeint
=
cfg
->
chargeint
*
HZ
;
lp
->
charge_state
=
ST_CHARGE_HAVE_CINT
;
lp
->
hupflags
|=
ISDN_MANCHARGE
;
}
return
-
ENODEV
;
retval
=
0
;
out:
return
retval
;
}
/*
...
...
@@ -2838,52 +2114,52 @@ int
isdn_net_getcfg
(
isdn_net_ioctl_cfg
*
cfg
)
{
isdn_net_dev
*
p
=
isdn_net_findif
(
cfg
->
name
);
isdn_net_local
*
lp
=
&
p
->
local
;
if
(
!
p
)
return
-
ENODEV
;
if
(
p
)
{
isdn_net_local
*
lp
=
&
p
->
local
;
strcpy
(
cfg
->
eaz
,
lp
->
msn
);
cfg
->
exclusive
=
lp
->
exclusive
;
if
(
lp
->
pre_device
>=
0
)
{
sprintf
(
cfg
->
drvid
,
"%s,%d"
,
dev
->
drvid
[
lp
->
pre_device
],
lp
->
pre_channel
);
}
else
cfg
->
drvid
[
0
]
=
'\0'
;
cfg
->
onhtime
=
lp
->
onhtime
;
cfg
->
charge
=
lp
->
charge
;
cfg
->
l2_proto
=
lp
->
l2_proto
;
cfg
->
l3_proto
=
lp
->
l3_proto
;
cfg
->
p_encap
=
lp
->
p_encap
;
cfg
->
secure
=
(
lp
->
flags
&
ISDN_NET_SECURE
)
?
1
:
0
;
cfg
->
callback
=
0
;
if
(
lp
->
flags
&
ISDN_NET_CALLBACK
)
cfg
->
callback
=
1
;
if
(
lp
->
flags
&
ISDN_NET_CBOUT
)
cfg
->
callback
=
2
;
cfg
->
cbhup
=
(
lp
->
flags
&
ISDN_NET_CBHUP
)
?
1
:
0
;
cfg
->
dialmode
=
lp
->
flags
&
ISDN_NET_DIALMODE_MASK
;
cfg
->
chargehup
=
(
lp
->
hupflags
&
4
)
?
1
:
0
;
cfg
->
ihup
=
(
lp
->
hupflags
&
8
)
?
1
:
0
;
cfg
->
cbdelay
=
lp
->
cbdelay
*
5
/
HZ
;
cfg
->
dialmax
=
lp
->
dialmax
;
cfg
->
triggercps
=
lp
->
triggercps
;
cfg
->
slavedelay
=
lp
->
slavedelay
/
HZ
;
cfg
->
chargeint
=
(
lp
->
hupflags
&
ISDN_CHARGEHUP
)
?
(
lp
->
chargeint
/
HZ
)
:
0
;
cfg
->
pppbind
=
lp
->
pppbind
;
cfg
->
dialtimeout
=
lp
->
dialtimeout
>=
0
?
lp
->
dialtimeout
/
HZ
:
-
1
;
cfg
->
dialwait
=
lp
->
dialwait
/
HZ
;
if
(
lp
->
slave
)
strcpy
(
cfg
->
slave
,
((
isdn_net_local
*
)
lp
->
slave
->
priv
)
->
name
);
else
cfg
->
slave
[
0
]
=
'\0'
;
if
(
lp
->
master
)
strcpy
(
cfg
->
master
,
((
isdn_net_local
*
)
lp
->
master
->
priv
)
->
name
);
else
cfg
->
master
[
0
]
=
'\0'
;
strcpy
(
cfg
->
eaz
,
lp
->
msn
);
cfg
->
exclusive
=
lp
->
exclusive
;
if
(
lp
->
pre_device
>=
0
)
{
sprintf
(
cfg
->
drvid
,
"%s,%d"
,
dev
->
drvid
[
lp
->
pre_device
],
lp
->
pre_channel
);
}
else
cfg
->
drvid
[
0
]
=
'\0'
;
cfg
->
onhtime
=
lp
->
onhtime
;
cfg
->
charge
=
lp
->
charge
;
cfg
->
l2_proto
=
lp
->
l2_proto
;
cfg
->
l3_proto
=
lp
->
l3_proto
;
cfg
->
p_encap
=
lp
->
p_encap
;
cfg
->
secure
=
(
lp
->
flags
&
ISDN_NET_SECURE
)
?
1
:
0
;
cfg
->
callback
=
0
;
if
(
lp
->
flags
&
ISDN_NET_CALLBACK
)
cfg
->
callback
=
1
;
if
(
lp
->
flags
&
ISDN_NET_CBOUT
)
cfg
->
callback
=
2
;
cfg
->
cbhup
=
(
lp
->
flags
&
ISDN_NET_CBHUP
)
?
1
:
0
;
cfg
->
dialmode
=
lp
->
flags
&
ISDN_NET_DIALMODE_MASK
;
cfg
->
chargehup
=
(
lp
->
hupflags
&
4
)
?
1
:
0
;
cfg
->
ihup
=
(
lp
->
hupflags
&
8
)
?
1
:
0
;
cfg
->
cbdelay
=
lp
->
cbdelay
*
5
/
HZ
;
cfg
->
dialmax
=
lp
->
dialmax
;
cfg
->
triggercps
=
lp
->
triggercps
;
cfg
->
slavedelay
=
lp
->
slavedelay
/
HZ
;
cfg
->
chargeint
=
(
lp
->
hupflags
&
ISDN_CHARGEHUP
)
?
(
lp
->
chargeint
/
HZ
)
:
0
;
cfg
->
pppbind
=
lp
->
pppbind
;
cfg
->
dialtimeout
=
lp
->
dialtimeout
>=
0
?
lp
->
dialtimeout
/
HZ
:
-
1
;
cfg
->
dialwait
=
lp
->
dialwait
/
HZ
;
if
(
lp
->
slave
)
strcpy
(
cfg
->
slave
,
((
isdn_net_local
*
)
lp
->
slave
->
priv
)
->
name
);
else
cfg
->
slave
[
0
]
=
'\0'
;
if
(
lp
->
master
)
strcpy
(
cfg
->
master
,
((
isdn_net_local
*
)
lp
->
master
->
priv
)
->
name
);
else
cfg
->
master
[
0
]
=
'\0'
;
return
0
;
}
return
-
ENODEV
;
return
0
;
}
/*
...
...
@@ -3067,14 +2343,12 @@ isdn_net_realrm(isdn_net_dev *p)
restore_flags
(
flags
);
return
-
EBUSY
;
}
#ifdef CONFIG_ISDN_X25
if
(
p
->
cprot
&&
p
->
cprot
->
pops
)
p
->
cprot
->
pops
->
proto_del
(
p
->
cprot
);
#endif
isdn_x25_realrm
(
p
);
/* Free all phone-entries */
isdn_net_rmallphone
(
p
);
/* If interface is bound exclusive, free channel-usage */
if
(
p
->
local
.
exclusive
!=
-
1
)
if
(
p
->
local
.
exclusive
)
isdn_unexclusive_channel
(
p
->
local
.
pre_device
,
p
->
local
.
pre_channel
);
if
(
p
->
local
.
master
)
{
/* It's a slave-device, so update master's slave-pointer if necessary */
...
...
@@ -3082,8 +2356,6 @@ isdn_net_realrm(isdn_net_dev *p)
((
isdn_net_local
*
)
(
p
->
local
.
master
->
priv
))
->
slave
=
p
->
local
.
slave
;
}
else
{
/* Unregister only if it's a master-device */
p
->
dev
.
hard_header_cache
=
p
->
local
.
org_hhc
;
p
->
dev
.
header_cache_update
=
p
->
local
.
org_hcu
;
unregister_netdev
(
&
p
->
dev
);
}
/* Unlink device from chain */
...
...
@@ -3150,3 +2422,193 @@ isdn_net_rmall(void)
restore_flags
(
flags
);
return
0
;
}
// ISDN_NET_ENCAP_IPTYP
// ethernet type field
// ======================================================================
static
int
isdn_iptyp_header
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
,
unsigned
short
type
,
void
*
daddr
,
void
*
saddr
,
unsigned
plen
)
{
put_u16
(
skb_push
(
skb
,
2
),
type
);
return
2
;
}
static
void
isdn_iptyp_receive
(
isdn_net_dev
*
p
,
isdn_net_local
*
olp
,
struct
sk_buff
*
skb
)
{
isdn_net_local
*
lp
=
&
p
->
local
;
isdn_net_reset_huptimer
(
lp
,
olp
);
get_u16
(
skb
->
data
,
&
skb
->
protocol
);
skb_pull
(
skb
,
2
);
netif_rx
(
skb
);
}
static
int
isdn_iptyp_setup
(
isdn_net_dev
*
p
)
{
p
->
dev
.
hard_header
=
isdn_iptyp_header
;
p
->
dev
.
hard_header_cache
=
NULL
;
p
->
dev
.
header_cache_update
=
NULL
;
p
->
dev
.
flags
=
IFF_NOARP
|
IFF_POINTOPOINT
;
p
->
local
.
receive
=
isdn_iptyp_receive
;
p
->
local
.
connected
=
isdn_net_device_wake_queue
;
p
->
local
.
disconnected
=
NULL
;
return
0
;
}
// ISDN_NET_ENCAP_UIHDLC
// HDLC with UI-Frames (for ispa with -h1 option) */
// ======================================================================
static
int
isdn_uihdlc_header
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
,
unsigned
short
type
,
void
*
daddr
,
void
*
saddr
,
unsigned
plen
)
{
put_u16
(
skb_push
(
skb
,
2
),
0x0103
);
return
2
;
}
static
void
isdn_uihdlc_receive
(
isdn_net_dev
*
p
,
isdn_net_local
*
olp
,
struct
sk_buff
*
skb
)
{
isdn_net_local
*
lp
=
&
p
->
local
;
isdn_net_reset_huptimer
(
lp
,
olp
);
skb_pull
(
skb
,
2
);
skb
->
protocol
=
htons
(
ETH_P_IP
);
netif_rx
(
skb
);
}
static
int
isdn_uihdlc_setup
(
isdn_net_dev
*
p
)
{
p
->
dev
.
hard_header
=
isdn_uihdlc_header
;
p
->
dev
.
hard_header_cache
=
NULL
;
p
->
dev
.
header_cache_update
=
NULL
;
p
->
dev
.
flags
=
IFF_NOARP
|
IFF_POINTOPOINT
;
p
->
local
.
receive
=
isdn_uihdlc_receive
;
p
->
local
.
connected
=
isdn_net_device_wake_queue
;
p
->
local
.
disconnected
=
NULL
;
return
0
;
}
// ISDN_NET_ENCAP_RAWIP
// RAW-IP without MAC-Header
// ======================================================================
static
void
isdn_rawip_receive
(
isdn_net_dev
*
p
,
isdn_net_local
*
olp
,
struct
sk_buff
*
skb
)
{
isdn_net_local
*
lp
=
&
p
->
local
;
isdn_net_reset_huptimer
(
lp
,
olp
);
skb
->
protocol
=
htons
(
ETH_P_IP
);
netif_rx
(
skb
);
}
static
int
isdn_rawip_setup
(
isdn_net_dev
*
p
)
{
p
->
dev
.
hard_header
=
NULL
;
p
->
dev
.
hard_header_cache
=
NULL
;
p
->
dev
.
header_cache_update
=
NULL
;
p
->
dev
.
flags
=
IFF_NOARP
|
IFF_POINTOPOINT
;
p
->
local
.
receive
=
isdn_rawip_receive
;
p
->
local
.
connected
=
isdn_net_device_wake_queue
;
p
->
local
.
disconnected
=
NULL
;
return
0
;
}
// ISDN_NET_ENCAP_ETHER
// Ethernet over ISDN
// ======================================================================
/* This is simply a copy from std. eth.c EXCEPT we pull ETH_HLEN
* instead of dev->hard_header_len off. This is done because the
* lowlevel-driver has already pulled off its stuff when we get
* here and this routine only gets called with p_encap == ETHER.
* Determine the packet's protocol ID. The rule here is that we
* assume 802.3 if the type field is short enough to be a length.
* This is normal practice and works for any 'now in use' protocol.
* FIXME
*/
static
unsigned
short
isdn_eth_type_trans
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
)
{
struct
ethhdr
*
eth
;
unsigned
char
*
rawp
;
skb
->
mac
.
raw
=
skb
->
data
;
skb_pull
(
skb
,
ETH_HLEN
);
eth
=
skb
->
mac
.
ethernet
;
if
(
*
eth
->
h_dest
&
1
)
{
if
(
memcmp
(
eth
->
h_dest
,
dev
->
broadcast
,
ETH_ALEN
)
==
0
)
skb
->
pkt_type
=
PACKET_BROADCAST
;
else
skb
->
pkt_type
=
PACKET_MULTICAST
;
}
/*
* This ALLMULTI check should be redundant by 1.4
* so don't forget to remove it.
*/
else
if
(
dev
->
flags
&
(
IFF_PROMISC
/*| IFF_ALLMULTI*/
))
{
if
(
memcmp
(
eth
->
h_dest
,
dev
->
dev_addr
,
ETH_ALEN
))
skb
->
pkt_type
=
PACKET_OTHERHOST
;
}
if
(
ntohs
(
eth
->
h_proto
)
>=
1536
)
return
eth
->
h_proto
;
rawp
=
skb
->
data
;
/*
* This is a magic hack to spot IPX packets. Older Novell breaks
* the protocol design and runs IPX over 802.3 without an 802.2 LLC
* layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This
* won't work for fault tolerant netware but does for the rest.
*/
if
(
*
(
unsigned
short
*
)
rawp
==
0xFFFF
)
return
htons
(
ETH_P_802_3
);
/*
* Real 802.2 LLC
*/
return
htons
(
ETH_P_802_2
);
}
static
void
isdn_ether_receive
(
isdn_net_dev
*
p
,
isdn_net_local
*
olp
,
struct
sk_buff
*
skb
)
{
isdn_net_local
*
lp
=
&
p
->
local
;
isdn_net_reset_huptimer
(
lp
,
olp
);
skb
->
protocol
=
isdn_eth_type_trans
(
skb
,
skb
->
dev
);
netif_rx
(
skb
);
}
static
int
isdn_ether_setup
(
isdn_net_dev
*
p
)
{
p
->
dev
.
hard_header
=
eth_header
;
p
->
dev
.
hard_header_cache
=
eth_header_cache
;
p
->
dev
.
header_cache_update
=
eth_header_cache_update
;
p
->
dev
.
flags
=
IFF_BROADCAST
|
IFF_MULTICAST
;
p
->
local
.
receive
=
isdn_ether_receive
;
p
->
local
.
connected
=
isdn_net_device_wake_queue
;
p
->
local
.
disconnected
=
NULL
;
return
0
;
}
drivers/isdn/i4l/isdn_net.h
View file @
dffdfbce
...
...
@@ -11,7 +11,10 @@
*
*/
/* Definitions for hupflags: */
#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/isdn.h>
/* Definitions for hupflags: */
#define ISDN_CHARGEHUP 4
/* We want to use the charge mechanism */
#define ISDN_INHUP 8
/* Even if incoming, close after huptimeout */
#define ISDN_MANCHARGE 16
/* Charge Interval manually set */
...
...
@@ -51,6 +54,13 @@ extern int isdn_net_dial_req(isdn_net_local *);
extern
void
isdn_net_writebuf_skb
(
isdn_net_local
*
lp
,
struct
sk_buff
*
skb
);
extern
void
isdn_net_write_super
(
isdn_net_local
*
lp
,
struct
sk_buff
*
skb
);
static
inline
void
isdn_net_reset_huptimer
(
isdn_net_local
*
lp
,
isdn_net_local
*
olp
)
{
olp
->
huptimer
=
0
;
lp
->
huptimer
=
0
;
}
#define ISDN_NET_MAX_QUEUE_LENGTH 2
/*
...
...
@@ -135,6 +145,18 @@ static __inline__ void isdn_net_rm_from_bundle(isdn_net_local *lp)
spin_unlock_irqrestore
(
&
master_lp
->
netdev
->
queue_lock
,
flags
);
}
/*
* wake up the network -> net_device queue.
* For slaves, wake the corresponding master interface.
*/
static
inline
void
isdn_net_device_wake_queue
(
isdn_net_local
*
lp
)
{
if
(
lp
->
master
)
netif_wake_queue
(
lp
->
master
);
else
netif_wake_queue
(
&
lp
->
netdev
->
dev
);
}
static
inline
int
put_u8
(
unsigned
char
*
p
,
u8
x
)
{
...
...
drivers/isdn/i4l/isdn_ppp.c
View file @
dffdfbce
...
...
@@ -14,6 +14,7 @@
#include <linux/smp_lock.h>
#include <linux/poll.h>
#include <linux/ppp-comp.h>
#include <linux/if_arp.h>
#include "isdn_common.h"
#include "isdn_ppp.h"
...
...
@@ -98,7 +99,7 @@ isdn_ppp_frame_log(char *info, char *data, int len, int maxlen,int unit,int slot
* note: it can happen, that we hangup/free the master before the slaves
* in this case we bind another lp to the master device
*/
int
static
void
isdn_ppp_free
(
isdn_net_local
*
lp
)
{
unsigned
long
flags
;
...
...
@@ -107,7 +108,7 @@ isdn_ppp_free(isdn_net_local * lp)
if
(
lp
->
ppp_slot
<
0
||
lp
->
ppp_slot
>
ISDN_MAX_CHANNELS
)
{
printk
(
KERN_ERR
"%s: ppp_slot(%d) out of range
\n
"
,
__FUNCTION__
,
lp
->
ppp_slot
);
return
0
;
return
;
}
save_flags
(
flags
);
...
...
@@ -128,7 +129,7 @@ isdn_ppp_free(isdn_net_local * lp)
printk
(
KERN_ERR
"%s: ppp_slot(%d) now invalid
\n
"
,
__FUNCTION__
,
lp
->
ppp_slot
);
restore_flags
(
flags
);
return
0
;
return
;
}
is
=
ippp_table
[
lp
->
ppp_slot
];
if
((
is
->
state
&
IPPP_CONNECT
))
...
...
@@ -143,7 +144,7 @@ isdn_ppp_free(isdn_net_local * lp)
lp
->
ppp_slot
=
-
1
;
/* is this OK ?? */
restore_flags
(
flags
);
return
0
;
return
;
}
/*
...
...
@@ -223,7 +224,7 @@ isdn_ppp_bind(isdn_net_local * lp)
* (wakes up daemon after B-channel connect)
*/
void
static
void
isdn_ppp_wakeup_daemon
(
isdn_net_local
*
lp
)
{
if
(
lp
->
ppp_slot
<
0
||
lp
->
ppp_slot
>=
ISDN_MAX_CHANNELS
)
{
...
...
@@ -961,14 +962,19 @@ static int isdn_ppp_strip_proto(struct sk_buff *skb)
/*
* handler for incoming packets on a syncPPP interface
*/
void
isdn_ppp_receive
(
isdn_net_dev
*
net_dev
,
isdn_net_local
*
lp
,
struct
sk_buff
*
skb
)
static
void
isdn_ppp_receive
(
isdn_net_dev
*
net_dev
,
isdn_net_local
*
lp
,
struct
sk_buff
*
skb
)
{
struct
ippp_struct
*
is
;
int
slot
;
int
proto
;
if
(
net_dev
->
local
.
master
)
BUG
();
// we're called with the master device always
/*
* If encapsulation is syncppp, don't reset
* huptimer on LCP packets.
*/
if
(
PPP_PROTOCOL
(
skb
->
data
)
!=
PPP_LCP
)
isdn_net_reset_huptimer
(
&
net_dev
->
local
,
lp
);
slot
=
lp
->
ppp_slot
;
if
(
slot
<
0
||
slot
>
ISDN_MAX_CHANNELS
)
{
...
...
@@ -2893,3 +2899,35 @@ static int isdn_ppp_set_compressor(struct ippp_struct *is, struct isdn_ppp_comp_
}
return
-
EINVAL
;
}
// ISDN_NET_ENCAP_SYNCPPP
// ======================================================================
static
int
isdn_ppp_header
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
,
unsigned
short
type
,
void
*
daddr
,
void
*
saddr
,
unsigned
plen
)
{
skb_push
(
skb
,
IPPP_MAX_HEADER
);
return
IPPP_MAX_HEADER
;
}
int
isdn_ppp_setup
(
isdn_net_dev
*
p
)
{
p
->
dev
.
hard_header
=
isdn_ppp_header
;
p
->
dev
.
hard_header_cache
=
NULL
;
p
->
dev
.
header_cache_update
=
NULL
;
p
->
dev
.
flags
=
IFF_NOARP
|
IFF_POINTOPOINT
;
p
->
dev
.
type
=
ARPHRD_PPP
;
/* change ARP type */
p
->
dev
.
addr_len
=
0
;
p
->
dev
.
do_ioctl
=
isdn_ppp_dev_ioctl
;
p
->
local
.
receive
=
isdn_ppp_receive
;
p
->
local
.
connected
=
isdn_ppp_wakeup_daemon
;
p
->
local
.
disconnected
=
isdn_ppp_free
;
return
0
;
}
drivers/isdn/i4l/isdn_ppp.h
View file @
dffdfbce
...
...
@@ -16,16 +16,37 @@ extern struct file_operations isdn_ppp_fops;
extern
int
isdn_ppp_init
(
void
);
extern
void
isdn_ppp_cleanup
(
void
);
extern
int
isdn_ppp_free
(
isdn_net_local
*
);
extern
int
isdn_ppp_bind
(
isdn_net_local
*
);
extern
int
isdn_ppp_xmit
(
struct
sk_buff
*
,
struct
net_device
*
);
extern
void
isdn_ppp_receive
(
isdn_net_dev
*
,
isdn_net_local
*
,
struct
sk_buff
*
);
extern
int
isdn_ppp_dev_ioctl
(
struct
net_device
*
,
struct
ifreq
*
,
int
);
extern
int
isdn_ppp_dial_slave
(
char
*
);
extern
void
isdn_ppp_wakeup_daemon
(
isdn_net_local
*
);
extern
int
isdn_ppp_hangup_slave
(
char
*
);
extern
int
isdn_ppp_register_compressor
(
struct
isdn_ppp_compressor
*
ipc
);
extern
int
isdn_ppp_unregister_compressor
(
struct
isdn_ppp_compressor
*
ipc
);
#ifdef CONFIG_ISDN_PPP
int
isdn_ppp_setup
(
isdn_net_dev
*
p
);
int
isdn_ppp_bind
(
isdn_net_local
*
);
int
isdn_ppp_xmit
(
struct
sk_buff
*
,
struct
net_device
*
);
#else
static
inline
int
isdn_ppp_setup
(
isdn_net_dev
*
p
)
{
printk
(
KERN_WARNING
"ISDN: SyncPPP support not configured
\n
"
);
return
-
EINVAL
;
}
static
inline
int
isdn_ppp_bind
(
isdn_net_local
*
)
{
return
0
;
}
static
inline
int
isdn_ppp_xmit
(
struct
sk_buff
*
,
struct
net_device
*
);
{
return
0
;
}
#endif
#define IPPP_OPEN 0x01
#define IPPP_CONNECT 0x02
...
...
include/linux/isdn.h
View file @
dffdfbce
...
...
@@ -75,7 +75,6 @@
#define ISDN_NET_ENCAP_UIHDLC 5
#define ISDN_NET_ENCAP_CISCOHDLCK 6
/* With SLARP and keepalive */
#define ISDN_NET_ENCAP_X25IFACE 7
/* Documentation/networking/x25-iface.txt*/
#define ISDN_NET_ENCAP_MAX_ENCAP ISDN_NET_ENCAP_X25IFACE
/* Facility which currently uses an ISDN-channel */
#define ISDN_USAGE_NONE 0
...
...
@@ -353,13 +352,6 @@ typedef struct isdn_net_local_s {
/* a particular channel (including */
/* the frame_cnt */
int
(
*
org_hhc
)(
struct
neighbour
*
neigh
,
struct
hh_cache
*
hh
);
/* Ptr to orig. header_cache_update */
void
(
*
org_hcu
)(
struct
hh_cache
*
,
struct
net_device
*
,
unsigned
char
*
);
int
pppbind
;
/* ippp device for bindings */
int
dialtimeout
;
/* How long shall we try on dialing? (jiffies) */
int
dialwait
;
/* How long shall we wait after failed attempt? (jiffies) */
...
...
@@ -379,6 +371,11 @@ typedef struct isdn_net_local_s {
char
cisco_debserint
;
/* debugging flag of cisco hdlc with slarp */
struct
timer_list
cisco_timer
;
struct
tq_struct
tqueue
;
void
(
*
receive
)(
struct
isdn_net_dev_s
*
p
,
struct
isdn_net_local_s
*
olp
,
struct
sk_buff
*
skb
);
void
(
*
connected
)(
struct
isdn_net_local_s
*
lp
);
void
(
*
disconnected
)(
struct
isdn_net_local_s
*
lp
);
}
isdn_net_local
;
/* the interface itself */
...
...
include/linux/isdn_ppp.h
View file @
dffdfbce
...
...
@@ -138,8 +138,6 @@ struct isdn_ppp_compressor {
extern
int
isdn_ppp_register_compressor
(
struct
isdn_ppp_compressor
*
);
extern
int
isdn_ppp_unregister_compressor
(
struct
isdn_ppp_compressor
*
);
extern
int
isdn_ppp_dial_slave
(
char
*
);
extern
int
isdn_ppp_hangup_slave
(
char
*
);
typedef
struct
{
unsigned
long
seqerrs
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment