2005-04-17 02:20:36 +04:00
/*
* Generic HDLC support routines for Linux
* HDLC support
*
2006-09-27 01:23:45 +04:00
* Copyright ( C ) 1999 - 2006 Krzysztof Halasa < khc @ pm . waw . pl >
2005-04-17 02:20:36 +04: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/errno.h>
2008-06-30 21:06:40 +04:00
# include <linux/hdlc.h>
2005-04-17 02:20:36 +04:00
# include <linux/if_arp.h>
2008-06-30 21:06:40 +04:00
# include <linux/inetdevice.h>
2005-04-17 02:20:36 +04:00
# include <linux/init.h>
2008-06-30 21:06:40 +04:00
# include <linux/kernel.h>
# include <linux/module.h>
2005-04-17 02:20:36 +04:00
# include <linux/pkt_sched.h>
2008-06-30 21:06:40 +04:00
# include <linux/poll.h>
2005-04-17 02:20:36 +04:00
# include <linux/rtnetlink.h>
2008-06-30 21:06:40 +04:00
# include <linux/skbuff.h>
2005-04-17 02:20:36 +04:00
2006-09-27 01:23:45 +04:00
static int raw_ioctl ( struct net_device * dev , struct ifreq * ifr ) ;
2005-07-12 23:08:43 +04:00
static __be16 raw_type_trans ( struct sk_buff * skb , struct net_device * dev )
2005-04-17 02:20:36 +04:00
{
2009-02-01 11:45:17 +03:00
return cpu_to_be16 ( ETH_P_IP ) ;
2005-04-17 02:20:36 +04:00
}
2006-09-27 01:23:45 +04:00
static struct hdlc_proto proto = {
. type_trans = raw_type_trans ,
. ioctl = raw_ioctl ,
. module = THIS_MODULE ,
} ;
static int raw_ioctl ( struct net_device * dev , struct ifreq * ifr )
2005-04-17 02:20:36 +04:00
{
raw_hdlc_proto __user * raw_s = ifr - > ifr_settings . ifs_ifsu . raw_hdlc ;
const size_t size = sizeof ( raw_hdlc_proto ) ;
raw_hdlc_proto new_settings ;
hdlc_device * hdlc = dev_to_hdlc ( dev ) ;
int result ;
switch ( ifr - > ifr_settings . type ) {
case IF_GET_PROTO :
2006-09-27 01:23:45 +04:00
if ( dev_to_hdlc ( dev ) - > proto ! = & proto )
return - EINVAL ;
2005-04-17 02:20:36 +04:00
ifr - > ifr_settings . type = IF_PROTO_HDLC ;
if ( ifr - > ifr_settings . size < size ) {
ifr - > ifr_settings . size = size ; /* data size wanted */
return - ENOBUFS ;
}
2006-09-27 01:23:45 +04:00
if ( copy_to_user ( raw_s , hdlc - > state , size ) )
2005-04-17 02:20:36 +04:00
return - EFAULT ;
return 0 ;
case IF_PROTO_HDLC :
if ( ! capable ( CAP_NET_ADMIN ) )
return - EPERM ;
if ( dev - > flags & IFF_UP )
return - EBUSY ;
if ( copy_from_user ( & new_settings , raw_s , size ) )
return - EFAULT ;
if ( new_settings . encoding = = ENCODING_DEFAULT )
new_settings . encoding = ENCODING_NRZ ;
if ( new_settings . parity = = PARITY_DEFAULT )
new_settings . parity = PARITY_CRC16_PR1_CCITT ;
result = hdlc - > attach ( dev , new_settings . encoding ,
new_settings . parity ) ;
if ( result )
return result ;
2008-02-02 00:37:12 +03:00
result = attach_hdlc_protocol ( dev , & proto ,
2006-09-27 01:23:45 +04:00
sizeof ( raw_hdlc_proto ) ) ;
if ( result )
return result ;
memcpy ( hdlc - > state , & new_settings , size ) ;
2005-04-17 02:20:36 +04:00
dev - > type = ARPHRD_RAWHDLC ;
2006-07-22 01:41:01 +04:00
netif_dormant_off ( dev ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
return - EINVAL ;
}
2006-09-27 01:23:45 +04: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 ( " Raw HDLC protocol support for generic HDLC " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;