2005-04-16 15:20:36 -07:00
/*
* Generic HDLC support routines for Linux
* HDLC 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/errno.h>
2008-06-30 19:06:40 +02:00
# include <linux/hdlc.h>
2005-04-16 15:20:36 -07:00
# include <linux/if_arp.h>
2008-06-30 19:06:40 +02:00
# include <linux/inetdevice.h>
2005-04-16 15:20:36 -07:00
# include <linux/init.h>
2008-06-30 19:06:40 +02:00
# include <linux/kernel.h>
# include <linux/module.h>
2005-04-16 15:20:36 -07:00
# include <linux/pkt_sched.h>
2008-06-30 19:06:40 +02:00
# include <linux/poll.h>
2005-04-16 15:20:36 -07:00
# include <linux/rtnetlink.h>
2008-06-30 19:06:40 +02:00
# include <linux/skbuff.h>
2005-04-16 15:20:36 -07:00
2006-09-26 23:23:45 +02:00
static int raw_ioctl ( struct net_device * dev , struct ifreq * ifr ) ;
2005-07-12 12:08:43 -07:00
static __be16 raw_type_trans ( struct sk_buff * skb , struct net_device * dev )
2005-04-16 15:20:36 -07:00
{
2009-02-01 00:45:17 -08:00
return cpu_to_be16 ( ETH_P_IP ) ;
2005-04-16 15:20:36 -07:00
}
2006-09-26 23:23:45 +02: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-16 15:20:36 -07: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-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_HDLC ;
if ( ifr - > ifr_settings . size < size ) {
ifr - > ifr_settings . size = size ; /* data size wanted */
return - ENOBUFS ;
}
2006-09-26 23:23:45 +02:00
if ( copy_to_user ( raw_s , hdlc - > state , size ) )
2005-04-16 15:20:36 -07: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-01 22:37:12 +01:00
result = attach_hdlc_protocol ( dev , & proto ,
2006-09-26 23:23:45 +02:00
sizeof ( raw_hdlc_proto ) ) ;
if ( result )
return result ;
memcpy ( hdlc - > state , & new_settings , size ) ;
2005-04-16 15:20:36 -07:00
dev - > type = ARPHRD_RAWHDLC ;
2015-12-03 21:12:31 +01:00
call_netdevice_notifiers ( NETDEV_POST_TYPE_CHANGE , dev ) ;
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 ( " Raw HDLC protocol support for generic HDLC " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;