2005-04-16 15:20:36 -07:00
/*
* Generic HDLC support routines for Linux
* Point - to - point protocol support
*
2006-09-26 23:23:45 +02:00
* Copyright ( C ) 1999 - 2006 Krzysztof Halasa < khc @ pm . waw . pl >
2005-04-16 15:20:36 -07:00
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms of version 2 of the GNU General Public License
* as published by the Free Software Foundation .
*/
# include <linux/module.h>
# include <linux/kernel.h>
# include <linux/slab.h>
# include <linux/poll.h>
# include <linux/errno.h>
# include <linux/if_arp.h>
# include <linux/init.h>
# include <linux/skbuff.h>
# include <linux/pkt_sched.h>
# include <linux/inetdevice.h>
# include <linux/lapb.h>
# include <linux/rtnetlink.h>
# include <linux/hdlc.h>
2006-09-26 23:23:45 +02:00
# include <net/syncppp.h>
struct ppp_state {
struct ppp_device pppdev ;
struct ppp_device * syncppp_ptr ;
int ( * old_change_mtu ) ( struct net_device * dev , int new_mtu ) ;
} ;
static int ppp_ioctl ( struct net_device * dev , struct ifreq * ifr ) ;
static inline struct ppp_state * state ( hdlc_device * hdlc )
{
return ( struct ppp_state * ) ( hdlc - > state ) ;
}
2005-04-16 15:20:36 -07:00
static int ppp_open ( struct net_device * dev )
{
hdlc_device * hdlc = dev_to_hdlc ( dev ) ;
void * old_ioctl ;
int result ;
2006-09-26 23:23:45 +02:00
dev - > priv = & state ( hdlc ) - > syncppp_ptr ;
state ( hdlc ) - > syncppp_ptr = & state ( hdlc ) - > pppdev ;
state ( hdlc ) - > pppdev . dev = dev ;
2005-04-16 15:20:36 -07:00
old_ioctl = dev - > do_ioctl ;
2006-09-26 23:23:45 +02:00
state ( hdlc ) - > old_change_mtu = dev - > change_mtu ;
sppp_attach ( & state ( hdlc ) - > pppdev ) ;
2005-04-16 15:20:36 -07:00
/* sppp_attach nukes them. We don't need syncppp's ioctl */
dev - > do_ioctl = old_ioctl ;
2006-09-26 23:23:45 +02:00
state ( hdlc ) - > pppdev . sppp . pp_flags & = ~ PP_CISCO ;
2005-04-16 15:20:36 -07:00
dev - > type = ARPHRD_PPP ;
result = sppp_open ( dev ) ;
if ( result ) {
sppp_detach ( dev ) ;
return result ;
}
return 0 ;
}
static void ppp_close ( struct net_device * dev )
{
hdlc_device * hdlc = dev_to_hdlc ( dev ) ;
sppp_close ( dev ) ;
sppp_detach ( dev ) ;
dev - > rebuild_header = NULL ;
2006-09-26 23:23:45 +02:00
dev - > change_mtu = state ( hdlc ) - > old_change_mtu ;
2005-04-16 15:20:36 -07:00
dev - > mtu = HDLC_MAX_MTU ;
dev - > hard_header_len = 16 ;
}
2005-07-12 12:08:43 -07:00
static __be16 ppp_type_trans ( struct sk_buff * skb , struct net_device * dev )
2005-04-16 15:20:36 -07:00
{
return __constant_htons ( ETH_P_WAN_PPP ) ;
}
2006-09-26 23:23:45 +02:00
static struct hdlc_proto proto = {
. open = ppp_open ,
. close = ppp_close ,
. type_trans = ppp_type_trans ,
. ioctl = ppp_ioctl ,
. module = THIS_MODULE ,
} ;
static int ppp_ioctl ( struct net_device * dev , struct ifreq * ifr )
2005-04-16 15:20:36 -07:00
{
hdlc_device * hdlc = dev_to_hdlc ( dev ) ;
int result ;
switch ( ifr - > ifr_settings . type ) {
case IF_GET_PROTO :
2006-09-26 23:23:45 +02:00
if ( dev_to_hdlc ( dev ) - > proto ! = & proto )
return - EINVAL ;
2005-04-16 15:20:36 -07:00
ifr - > ifr_settings . type = IF_PROTO_PPP ;
return 0 ; /* return protocol only, no settable parameters */
case IF_PROTO_PPP :
if ( ! capable ( CAP_NET_ADMIN ) )
return - EPERM ;
if ( dev - > flags & IFF_UP )
return - EBUSY ;
/* no settable parameters */
result = hdlc - > attach ( dev , ENCODING_NRZ , PARITY_CRC16_PR1_CCITT ) ;
if ( result )
return result ;
2006-09-26 23:23:45 +02:00
result = attach_hdlc_protocol ( dev , & proto , NULL ,
sizeof ( struct ppp_state ) ) ;
if ( result )
return result ;
2005-04-16 15:20:36 -07:00
dev - > hard_start_xmit = hdlc - > xmit ;
dev - > type = ARPHRD_PPP ;
2006-07-21 14:41:01 -07:00
netif_dormant_off ( dev ) ;
2005-04-16 15:20:36 -07:00
return 0 ;
}
return - EINVAL ;
}
2006-09-26 23:23:45 +02:00
static int __init mod_init ( void )
{
register_hdlc_protocol ( & proto ) ;
return 0 ;
}
static void __exit mod_exit ( void )
{
unregister_hdlc_protocol ( & proto ) ;
}
module_init ( mod_init ) ;
module_exit ( mod_exit ) ;
MODULE_AUTHOR ( " Krzysztof Halasa <khc@pm.waw.pl> " ) ;
MODULE_DESCRIPTION ( " PPP protocol support for generic HDLC " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;