/* * Generic HDLC support routines for Linux * * Copyright (C) 1999 - 2001 Krzysztof Halasa * * 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 of the License, or * (at your option) any later version. * * Current status: * - this is work in progress * - not heavily tested on SMP * - currently supported: * * raw IP-in-HDLC * * Cisco HDLC * * Frame Relay with ANSI or CCITT LMI (both user and network side) * * PPP * * X.25 * * Use sethdlc utility to set line parameters, protocol and PVCs */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include static const char* version = "HDLC support module revision 1.11"; static int hdlc_change_mtu(struct net_device *dev, int new_mtu) { if ((new_mtu < 68) || (new_mtu > HDLC_MAX_MTU)) return -EINVAL; dev->mtu = new_mtu; return 0; } static struct net_device_stats *hdlc_get_stats(struct net_device *dev) { return &dev_to_hdlc(dev)->stats; } static int hdlc_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *p) { dev_to_hdlc(dev)->netif_rx(skb); return 0; } #ifndef CONFIG_HDLC_RAW #define hdlc_raw_ioctl(hdlc, ifr) -ENOSYS #endif #ifndef CONFIG_HDLC_PPP #define hdlc_ppp_ioctl(hdlc, ifr) -ENOSYS #endif #ifndef CONFIG_HDLC_CISCO #define hdlc_cisco_ioctl(hdlc, ifr) -ENOSYS #endif #ifndef CONFIG_HDLC_FR #define hdlc_fr_ioctl(hdlc, ifr) -ENOSYS #endif #ifndef CONFIG_HDLC_X25 #define hdlc_x25_ioctl(hdlc, ifr) -ENOSYS #endif int hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { hdlc_device *hdlc = dev_to_hdlc(dev); unsigned int proto; if (cmd != SIOCWANDEV) return -EINVAL; switch(ifr->ifr_settings.type) { case IF_PROTO_HDLC: case IF_PROTO_PPP: case IF_PROTO_CISCO: case IF_PROTO_FR: case IF_PROTO_X25: proto = ifr->ifr_settings.type; break; default: proto = hdlc->proto; } switch(proto) { case IF_PROTO_HDLC: return hdlc_raw_ioctl(hdlc, ifr); case IF_PROTO_PPP: return hdlc_ppp_ioctl(hdlc, ifr); case IF_PROTO_CISCO: return hdlc_cisco_ioctl(hdlc, ifr); case IF_PROTO_FR: return hdlc_fr_ioctl(hdlc, ifr); case IF_PROTO_X25: return hdlc_x25_ioctl(hdlc, ifr); default: return -EINVAL; } } int register_hdlc_device(hdlc_device *hdlc) { int result; struct net_device *dev = hdlc_to_dev(hdlc); dev->get_stats = hdlc_get_stats; dev->change_mtu = hdlc_change_mtu; dev->mtu = HDLC_MAX_MTU; dev->type = ARPHRD_RAWHDLC; dev->hard_header_len = 16; dev->flags = IFF_POINTOPOINT | IFF_NOARP; hdlc->proto = -1; hdlc->proto_detach = NULL; result = dev_alloc_name(dev, "hdlc%d"); if (result<0) return result; result = register_netdev(dev); if (result != 0) return -EIO; MOD_INC_USE_COUNT; return 0; } void unregister_hdlc_device(hdlc_device *hdlc) { hdlc_proto_detach(hdlc); unregister_netdev(hdlc_to_dev(hdlc)); MOD_DEC_USE_COUNT; } MODULE_AUTHOR("Krzysztof Halasa "); MODULE_DESCRIPTION("HDLC support module"); MODULE_LICENSE("GPL"); EXPORT_SYMBOL(hdlc_ioctl); EXPORT_SYMBOL(register_hdlc_device); EXPORT_SYMBOL(unregister_hdlc_device); struct packet_type hdlc_packet_type= { __constant_htons(ETH_P_HDLC), NULL, hdlc_rcv, NULL, NULL }; static int __init hdlc_module_init(void) { printk(KERN_INFO "%s\n", version); dev_add_pack(&hdlc_packet_type); return 0; } static void __exit hdlc_module_exit(void) { dev_remove_pack(&hdlc_packet_type); } module_init(hdlc_module_init); module_exit(hdlc_module_exit);