Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | /* * Generic HDLC support routines for Linux * Point-to-point protocol support * * Copyright (C) 1999 - 2001 Krzysztof Halasa <khc@pm.waw.pl> * * 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. */ #include <linux/config.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/slab.h> #include <linux/poll.h> #include <linux/sched.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> static int ppp_open(hdlc_device *hdlc) { struct net_device *dev = hdlc_to_dev(hdlc); void *old_ioctl; int result; dev->priv = &hdlc->state.ppp.syncppp_ptr; hdlc->state.ppp.syncppp_ptr = &hdlc->state.ppp.pppdev; hdlc->state.ppp.pppdev.dev = dev; old_ioctl = dev->do_ioctl; hdlc->state.ppp.old_change_mtu = dev->change_mtu; sppp_attach(&hdlc->state.ppp.pppdev); /* sppp_attach nukes them. We don't need syncppp's ioctl */ dev->do_ioctl = old_ioctl; hdlc->state.ppp.pppdev.sppp.pp_flags &= ~PP_CISCO; dev->type = ARPHRD_PPP; result = sppp_open(dev); if (result) { sppp_detach(dev); return result; } return 0; } static void ppp_close(hdlc_device *hdlc) { struct net_device *dev = hdlc_to_dev(hdlc); sppp_close(dev); sppp_detach(dev); dev->rebuild_header = NULL; dev->change_mtu = hdlc->state.ppp.old_change_mtu; dev->mtu = HDLC_MAX_MTU; dev->hard_header_len = 16; } static void ppp_rx(struct sk_buff *skb) { skb->protocol = htons(ETH_P_WAN_PPP); netif_rx(skb); } int hdlc_ppp_ioctl(hdlc_device *hdlc, struct ifreq *ifr) { struct net_device *dev = hdlc_to_dev(hdlc); int result; switch (ifr->ifr_settings->type) { case IF_GET_PROTO: 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 */ hdlc_detach(hdlc); result=hdlc->attach(hdlc, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT); if (result) { hdlc->proto = -1; return result; } hdlc->open = ppp_open; hdlc->stop = ppp_close; hdlc->netif_rx = ppp_rx; hdlc->proto = IF_PROTO_PPP; dev->hard_start_xmit = hdlc->xmit; dev->hard_header = NULL; dev->type = ARPHRD_PPP; dev->addr_len = 0; return 0; } return -EINVAL; } |