1*1da177e4SLinus Torvalds /* 2*1da177e4SLinus Torvalds * Generic HDLC support routines for Linux 3*1da177e4SLinus Torvalds * Cisco HDLC support 4*1da177e4SLinus Torvalds * 5*1da177e4SLinus Torvalds * Copyright (C) 2000 - 2003 Krzysztof Halasa <khc@pm.waw.pl> 6*1da177e4SLinus Torvalds * 7*1da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or modify it 8*1da177e4SLinus Torvalds * under the terms of version 2 of the GNU General Public License 9*1da177e4SLinus Torvalds * as published by the Free Software Foundation. 10*1da177e4SLinus Torvalds */ 11*1da177e4SLinus Torvalds 12*1da177e4SLinus Torvalds #include <linux/module.h> 13*1da177e4SLinus Torvalds #include <linux/kernel.h> 14*1da177e4SLinus Torvalds #include <linux/slab.h> 15*1da177e4SLinus Torvalds #include <linux/poll.h> 16*1da177e4SLinus Torvalds #include <linux/errno.h> 17*1da177e4SLinus Torvalds #include <linux/if_arp.h> 18*1da177e4SLinus Torvalds #include <linux/init.h> 19*1da177e4SLinus Torvalds #include <linux/skbuff.h> 20*1da177e4SLinus Torvalds #include <linux/pkt_sched.h> 21*1da177e4SLinus Torvalds #include <linux/inetdevice.h> 22*1da177e4SLinus Torvalds #include <linux/lapb.h> 23*1da177e4SLinus Torvalds #include <linux/rtnetlink.h> 24*1da177e4SLinus Torvalds #include <linux/hdlc.h> 25*1da177e4SLinus Torvalds 26*1da177e4SLinus Torvalds #undef DEBUG_HARD_HEADER 27*1da177e4SLinus Torvalds 28*1da177e4SLinus Torvalds #define CISCO_MULTICAST 0x8F /* Cisco multicast address */ 29*1da177e4SLinus Torvalds #define CISCO_UNICAST 0x0F /* Cisco unicast address */ 30*1da177e4SLinus Torvalds #define CISCO_KEEPALIVE 0x8035 /* Cisco keepalive protocol */ 31*1da177e4SLinus Torvalds #define CISCO_SYS_INFO 0x2000 /* Cisco interface/system info */ 32*1da177e4SLinus Torvalds #define CISCO_ADDR_REQ 0 /* Cisco address request */ 33*1da177e4SLinus Torvalds #define CISCO_ADDR_REPLY 1 /* Cisco address reply */ 34*1da177e4SLinus Torvalds #define CISCO_KEEPALIVE_REQ 2 /* Cisco keepalive request */ 35*1da177e4SLinus Torvalds 36*1da177e4SLinus Torvalds 37*1da177e4SLinus Torvalds static int cisco_hard_header(struct sk_buff *skb, struct net_device *dev, 38*1da177e4SLinus Torvalds u16 type, void *daddr, void *saddr, 39*1da177e4SLinus Torvalds unsigned int len) 40*1da177e4SLinus Torvalds { 41*1da177e4SLinus Torvalds hdlc_header *data; 42*1da177e4SLinus Torvalds #ifdef DEBUG_HARD_HEADER 43*1da177e4SLinus Torvalds printk(KERN_DEBUG "%s: cisco_hard_header called\n", dev->name); 44*1da177e4SLinus Torvalds #endif 45*1da177e4SLinus Torvalds 46*1da177e4SLinus Torvalds skb_push(skb, sizeof(hdlc_header)); 47*1da177e4SLinus Torvalds data = (hdlc_header*)skb->data; 48*1da177e4SLinus Torvalds if (type == CISCO_KEEPALIVE) 49*1da177e4SLinus Torvalds data->address = CISCO_MULTICAST; 50*1da177e4SLinus Torvalds else 51*1da177e4SLinus Torvalds data->address = CISCO_UNICAST; 52*1da177e4SLinus Torvalds data->control = 0; 53*1da177e4SLinus Torvalds data->protocol = htons(type); 54*1da177e4SLinus Torvalds 55*1da177e4SLinus Torvalds return sizeof(hdlc_header); 56*1da177e4SLinus Torvalds } 57*1da177e4SLinus Torvalds 58*1da177e4SLinus Torvalds 59*1da177e4SLinus Torvalds 60*1da177e4SLinus Torvalds static void cisco_keepalive_send(struct net_device *dev, u32 type, 61*1da177e4SLinus Torvalds u32 par1, u32 par2) 62*1da177e4SLinus Torvalds { 63*1da177e4SLinus Torvalds struct sk_buff *skb; 64*1da177e4SLinus Torvalds cisco_packet *data; 65*1da177e4SLinus Torvalds 66*1da177e4SLinus Torvalds skb = dev_alloc_skb(sizeof(hdlc_header) + sizeof(cisco_packet)); 67*1da177e4SLinus Torvalds if (!skb) { 68*1da177e4SLinus Torvalds printk(KERN_WARNING 69*1da177e4SLinus Torvalds "%s: Memory squeeze on cisco_keepalive_send()\n", 70*1da177e4SLinus Torvalds dev->name); 71*1da177e4SLinus Torvalds return; 72*1da177e4SLinus Torvalds } 73*1da177e4SLinus Torvalds skb_reserve(skb, 4); 74*1da177e4SLinus Torvalds cisco_hard_header(skb, dev, CISCO_KEEPALIVE, NULL, NULL, 0); 75*1da177e4SLinus Torvalds data = (cisco_packet*)skb->tail; 76*1da177e4SLinus Torvalds 77*1da177e4SLinus Torvalds data->type = htonl(type); 78*1da177e4SLinus Torvalds data->par1 = htonl(par1); 79*1da177e4SLinus Torvalds data->par2 = htonl(par2); 80*1da177e4SLinus Torvalds data->rel = 0xFFFF; 81*1da177e4SLinus Torvalds /* we will need do_div here if 1000 % HZ != 0 */ 82*1da177e4SLinus Torvalds data->time = htonl((jiffies - INITIAL_JIFFIES) * (1000 / HZ)); 83*1da177e4SLinus Torvalds 84*1da177e4SLinus Torvalds skb_put(skb, sizeof(cisco_packet)); 85*1da177e4SLinus Torvalds skb->priority = TC_PRIO_CONTROL; 86*1da177e4SLinus Torvalds skb->dev = dev; 87*1da177e4SLinus Torvalds skb->nh.raw = skb->data; 88*1da177e4SLinus Torvalds 89*1da177e4SLinus Torvalds dev_queue_xmit(skb); 90*1da177e4SLinus Torvalds } 91*1da177e4SLinus Torvalds 92*1da177e4SLinus Torvalds 93*1da177e4SLinus Torvalds 94*1da177e4SLinus Torvalds static unsigned short cisco_type_trans(struct sk_buff *skb, 95*1da177e4SLinus Torvalds struct net_device *dev) 96*1da177e4SLinus Torvalds { 97*1da177e4SLinus Torvalds hdlc_header *data = (hdlc_header*)skb->data; 98*1da177e4SLinus Torvalds 99*1da177e4SLinus Torvalds if (skb->len < sizeof(hdlc_header)) 100*1da177e4SLinus Torvalds return __constant_htons(ETH_P_HDLC); 101*1da177e4SLinus Torvalds 102*1da177e4SLinus Torvalds if (data->address != CISCO_MULTICAST && 103*1da177e4SLinus Torvalds data->address != CISCO_UNICAST) 104*1da177e4SLinus Torvalds return __constant_htons(ETH_P_HDLC); 105*1da177e4SLinus Torvalds 106*1da177e4SLinus Torvalds switch(data->protocol) { 107*1da177e4SLinus Torvalds case __constant_htons(ETH_P_IP): 108*1da177e4SLinus Torvalds case __constant_htons(ETH_P_IPX): 109*1da177e4SLinus Torvalds case __constant_htons(ETH_P_IPV6): 110*1da177e4SLinus Torvalds skb_pull(skb, sizeof(hdlc_header)); 111*1da177e4SLinus Torvalds return data->protocol; 112*1da177e4SLinus Torvalds default: 113*1da177e4SLinus Torvalds return __constant_htons(ETH_P_HDLC); 114*1da177e4SLinus Torvalds } 115*1da177e4SLinus Torvalds } 116*1da177e4SLinus Torvalds 117*1da177e4SLinus Torvalds 118*1da177e4SLinus Torvalds static int cisco_rx(struct sk_buff *skb) 119*1da177e4SLinus Torvalds { 120*1da177e4SLinus Torvalds struct net_device *dev = skb->dev; 121*1da177e4SLinus Torvalds hdlc_device *hdlc = dev_to_hdlc(dev); 122*1da177e4SLinus Torvalds hdlc_header *data = (hdlc_header*)skb->data; 123*1da177e4SLinus Torvalds cisco_packet *cisco_data; 124*1da177e4SLinus Torvalds struct in_device *in_dev; 125*1da177e4SLinus Torvalds u32 addr, mask; 126*1da177e4SLinus Torvalds 127*1da177e4SLinus Torvalds if (skb->len < sizeof(hdlc_header)) 128*1da177e4SLinus Torvalds goto rx_error; 129*1da177e4SLinus Torvalds 130*1da177e4SLinus Torvalds if (data->address != CISCO_MULTICAST && 131*1da177e4SLinus Torvalds data->address != CISCO_UNICAST) 132*1da177e4SLinus Torvalds goto rx_error; 133*1da177e4SLinus Torvalds 134*1da177e4SLinus Torvalds switch(ntohs(data->protocol)) { 135*1da177e4SLinus Torvalds case CISCO_SYS_INFO: 136*1da177e4SLinus Torvalds /* Packet is not needed, drop it. */ 137*1da177e4SLinus Torvalds dev_kfree_skb_any(skb); 138*1da177e4SLinus Torvalds return NET_RX_SUCCESS; 139*1da177e4SLinus Torvalds 140*1da177e4SLinus Torvalds case CISCO_KEEPALIVE: 141*1da177e4SLinus Torvalds if (skb->len != sizeof(hdlc_header) + CISCO_PACKET_LEN && 142*1da177e4SLinus Torvalds skb->len != sizeof(hdlc_header) + CISCO_BIG_PACKET_LEN) { 143*1da177e4SLinus Torvalds printk(KERN_INFO "%s: Invalid length of Cisco " 144*1da177e4SLinus Torvalds "control packet (%d bytes)\n", 145*1da177e4SLinus Torvalds dev->name, skb->len); 146*1da177e4SLinus Torvalds goto rx_error; 147*1da177e4SLinus Torvalds } 148*1da177e4SLinus Torvalds 149*1da177e4SLinus Torvalds cisco_data = (cisco_packet*)(skb->data + sizeof(hdlc_header)); 150*1da177e4SLinus Torvalds 151*1da177e4SLinus Torvalds switch(ntohl (cisco_data->type)) { 152*1da177e4SLinus Torvalds case CISCO_ADDR_REQ: /* Stolen from syncppp.c :-) */ 153*1da177e4SLinus Torvalds in_dev = dev->ip_ptr; 154*1da177e4SLinus Torvalds addr = 0; 155*1da177e4SLinus Torvalds mask = ~0; /* is the mask correct? */ 156*1da177e4SLinus Torvalds 157*1da177e4SLinus Torvalds if (in_dev != NULL) { 158*1da177e4SLinus Torvalds struct in_ifaddr **ifap = &in_dev->ifa_list; 159*1da177e4SLinus Torvalds 160*1da177e4SLinus Torvalds while (*ifap != NULL) { 161*1da177e4SLinus Torvalds if (strcmp(dev->name, 162*1da177e4SLinus Torvalds (*ifap)->ifa_label) == 0) { 163*1da177e4SLinus Torvalds addr = (*ifap)->ifa_local; 164*1da177e4SLinus Torvalds mask = (*ifap)->ifa_mask; 165*1da177e4SLinus Torvalds break; 166*1da177e4SLinus Torvalds } 167*1da177e4SLinus Torvalds ifap = &(*ifap)->ifa_next; 168*1da177e4SLinus Torvalds } 169*1da177e4SLinus Torvalds 170*1da177e4SLinus Torvalds cisco_keepalive_send(dev, CISCO_ADDR_REPLY, 171*1da177e4SLinus Torvalds addr, mask); 172*1da177e4SLinus Torvalds } 173*1da177e4SLinus Torvalds dev_kfree_skb_any(skb); 174*1da177e4SLinus Torvalds return NET_RX_SUCCESS; 175*1da177e4SLinus Torvalds 176*1da177e4SLinus Torvalds case CISCO_ADDR_REPLY: 177*1da177e4SLinus Torvalds printk(KERN_INFO "%s: Unexpected Cisco IP address " 178*1da177e4SLinus Torvalds "reply\n", dev->name); 179*1da177e4SLinus Torvalds goto rx_error; 180*1da177e4SLinus Torvalds 181*1da177e4SLinus Torvalds case CISCO_KEEPALIVE_REQ: 182*1da177e4SLinus Torvalds hdlc->state.cisco.rxseq = ntohl(cisco_data->par1); 183*1da177e4SLinus Torvalds if (hdlc->state.cisco.request_sent && 184*1da177e4SLinus Torvalds ntohl(cisco_data->par2)==hdlc->state.cisco.txseq) { 185*1da177e4SLinus Torvalds hdlc->state.cisco.last_poll = jiffies; 186*1da177e4SLinus Torvalds if (!hdlc->state.cisco.up) { 187*1da177e4SLinus Torvalds u32 sec, min, hrs, days; 188*1da177e4SLinus Torvalds sec = ntohl(cisco_data->time) / 1000; 189*1da177e4SLinus Torvalds min = sec / 60; sec -= min * 60; 190*1da177e4SLinus Torvalds hrs = min / 60; min -= hrs * 60; 191*1da177e4SLinus Torvalds days = hrs / 24; hrs -= days * 24; 192*1da177e4SLinus Torvalds printk(KERN_INFO "%s: Link up (peer " 193*1da177e4SLinus Torvalds "uptime %ud%uh%um%us)\n", 194*1da177e4SLinus Torvalds dev->name, days, hrs, 195*1da177e4SLinus Torvalds min, sec); 196*1da177e4SLinus Torvalds netif_carrier_on(dev); 197*1da177e4SLinus Torvalds hdlc->state.cisco.up = 1; 198*1da177e4SLinus Torvalds } 199*1da177e4SLinus Torvalds } 200*1da177e4SLinus Torvalds 201*1da177e4SLinus Torvalds dev_kfree_skb_any(skb); 202*1da177e4SLinus Torvalds return NET_RX_SUCCESS; 203*1da177e4SLinus Torvalds } /* switch(keepalive type) */ 204*1da177e4SLinus Torvalds } /* switch(protocol) */ 205*1da177e4SLinus Torvalds 206*1da177e4SLinus Torvalds printk(KERN_INFO "%s: Unsupported protocol %x\n", dev->name, 207*1da177e4SLinus Torvalds data->protocol); 208*1da177e4SLinus Torvalds dev_kfree_skb_any(skb); 209*1da177e4SLinus Torvalds return NET_RX_DROP; 210*1da177e4SLinus Torvalds 211*1da177e4SLinus Torvalds rx_error: 212*1da177e4SLinus Torvalds hdlc->stats.rx_errors++; /* Mark error */ 213*1da177e4SLinus Torvalds dev_kfree_skb_any(skb); 214*1da177e4SLinus Torvalds return NET_RX_DROP; 215*1da177e4SLinus Torvalds } 216*1da177e4SLinus Torvalds 217*1da177e4SLinus Torvalds 218*1da177e4SLinus Torvalds 219*1da177e4SLinus Torvalds static void cisco_timer(unsigned long arg) 220*1da177e4SLinus Torvalds { 221*1da177e4SLinus Torvalds struct net_device *dev = (struct net_device *)arg; 222*1da177e4SLinus Torvalds hdlc_device *hdlc = dev_to_hdlc(dev); 223*1da177e4SLinus Torvalds 224*1da177e4SLinus Torvalds if (hdlc->state.cisco.up && 225*1da177e4SLinus Torvalds time_after(jiffies, hdlc->state.cisco.last_poll + 226*1da177e4SLinus Torvalds hdlc->state.cisco.settings.timeout * HZ)) { 227*1da177e4SLinus Torvalds hdlc->state.cisco.up = 0; 228*1da177e4SLinus Torvalds printk(KERN_INFO "%s: Link down\n", dev->name); 229*1da177e4SLinus Torvalds netif_carrier_off(dev); 230*1da177e4SLinus Torvalds } 231*1da177e4SLinus Torvalds 232*1da177e4SLinus Torvalds cisco_keepalive_send(dev, CISCO_KEEPALIVE_REQ, 233*1da177e4SLinus Torvalds ++hdlc->state.cisco.txseq, 234*1da177e4SLinus Torvalds hdlc->state.cisco.rxseq); 235*1da177e4SLinus Torvalds hdlc->state.cisco.request_sent = 1; 236*1da177e4SLinus Torvalds hdlc->state.cisco.timer.expires = jiffies + 237*1da177e4SLinus Torvalds hdlc->state.cisco.settings.interval * HZ; 238*1da177e4SLinus Torvalds hdlc->state.cisco.timer.function = cisco_timer; 239*1da177e4SLinus Torvalds hdlc->state.cisco.timer.data = arg; 240*1da177e4SLinus Torvalds add_timer(&hdlc->state.cisco.timer); 241*1da177e4SLinus Torvalds } 242*1da177e4SLinus Torvalds 243*1da177e4SLinus Torvalds 244*1da177e4SLinus Torvalds 245*1da177e4SLinus Torvalds static void cisco_start(struct net_device *dev) 246*1da177e4SLinus Torvalds { 247*1da177e4SLinus Torvalds hdlc_device *hdlc = dev_to_hdlc(dev); 248*1da177e4SLinus Torvalds hdlc->state.cisco.up = 0; 249*1da177e4SLinus Torvalds hdlc->state.cisco.request_sent = 0; 250*1da177e4SLinus Torvalds hdlc->state.cisco.txseq = hdlc->state.cisco.rxseq = 0; 251*1da177e4SLinus Torvalds 252*1da177e4SLinus Torvalds init_timer(&hdlc->state.cisco.timer); 253*1da177e4SLinus Torvalds hdlc->state.cisco.timer.expires = jiffies + HZ; /*First poll after 1s*/ 254*1da177e4SLinus Torvalds hdlc->state.cisco.timer.function = cisco_timer; 255*1da177e4SLinus Torvalds hdlc->state.cisco.timer.data = (unsigned long)dev; 256*1da177e4SLinus Torvalds add_timer(&hdlc->state.cisco.timer); 257*1da177e4SLinus Torvalds } 258*1da177e4SLinus Torvalds 259*1da177e4SLinus Torvalds 260*1da177e4SLinus Torvalds 261*1da177e4SLinus Torvalds static void cisco_stop(struct net_device *dev) 262*1da177e4SLinus Torvalds { 263*1da177e4SLinus Torvalds hdlc_device *hdlc = dev_to_hdlc(dev); 264*1da177e4SLinus Torvalds del_timer_sync(&hdlc->state.cisco.timer); 265*1da177e4SLinus Torvalds if (netif_carrier_ok(dev)) 266*1da177e4SLinus Torvalds netif_carrier_off(dev); 267*1da177e4SLinus Torvalds hdlc->state.cisco.up = 0; 268*1da177e4SLinus Torvalds hdlc->state.cisco.request_sent = 0; 269*1da177e4SLinus Torvalds } 270*1da177e4SLinus Torvalds 271*1da177e4SLinus Torvalds 272*1da177e4SLinus Torvalds 273*1da177e4SLinus Torvalds int hdlc_cisco_ioctl(struct net_device *dev, struct ifreq *ifr) 274*1da177e4SLinus Torvalds { 275*1da177e4SLinus Torvalds cisco_proto __user *cisco_s = ifr->ifr_settings.ifs_ifsu.cisco; 276*1da177e4SLinus Torvalds const size_t size = sizeof(cisco_proto); 277*1da177e4SLinus Torvalds cisco_proto new_settings; 278*1da177e4SLinus Torvalds hdlc_device *hdlc = dev_to_hdlc(dev); 279*1da177e4SLinus Torvalds int result; 280*1da177e4SLinus Torvalds 281*1da177e4SLinus Torvalds switch (ifr->ifr_settings.type) { 282*1da177e4SLinus Torvalds case IF_GET_PROTO: 283*1da177e4SLinus Torvalds ifr->ifr_settings.type = IF_PROTO_CISCO; 284*1da177e4SLinus Torvalds if (ifr->ifr_settings.size < size) { 285*1da177e4SLinus Torvalds ifr->ifr_settings.size = size; /* data size wanted */ 286*1da177e4SLinus Torvalds return -ENOBUFS; 287*1da177e4SLinus Torvalds } 288*1da177e4SLinus Torvalds if (copy_to_user(cisco_s, &hdlc->state.cisco.settings, size)) 289*1da177e4SLinus Torvalds return -EFAULT; 290*1da177e4SLinus Torvalds return 0; 291*1da177e4SLinus Torvalds 292*1da177e4SLinus Torvalds case IF_PROTO_CISCO: 293*1da177e4SLinus Torvalds if(!capable(CAP_NET_ADMIN)) 294*1da177e4SLinus Torvalds return -EPERM; 295*1da177e4SLinus Torvalds 296*1da177e4SLinus Torvalds if(dev->flags & IFF_UP) 297*1da177e4SLinus Torvalds return -EBUSY; 298*1da177e4SLinus Torvalds 299*1da177e4SLinus Torvalds if (copy_from_user(&new_settings, cisco_s, size)) 300*1da177e4SLinus Torvalds return -EFAULT; 301*1da177e4SLinus Torvalds 302*1da177e4SLinus Torvalds if (new_settings.interval < 1 || 303*1da177e4SLinus Torvalds new_settings.timeout < 2) 304*1da177e4SLinus Torvalds return -EINVAL; 305*1da177e4SLinus Torvalds 306*1da177e4SLinus Torvalds result=hdlc->attach(dev, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT); 307*1da177e4SLinus Torvalds 308*1da177e4SLinus Torvalds if (result) 309*1da177e4SLinus Torvalds return result; 310*1da177e4SLinus Torvalds 311*1da177e4SLinus Torvalds hdlc_proto_detach(hdlc); 312*1da177e4SLinus Torvalds memcpy(&hdlc->state.cisco.settings, &new_settings, size); 313*1da177e4SLinus Torvalds memset(&hdlc->proto, 0, sizeof(hdlc->proto)); 314*1da177e4SLinus Torvalds 315*1da177e4SLinus Torvalds hdlc->proto.start = cisco_start; 316*1da177e4SLinus Torvalds hdlc->proto.stop = cisco_stop; 317*1da177e4SLinus Torvalds hdlc->proto.netif_rx = cisco_rx; 318*1da177e4SLinus Torvalds hdlc->proto.type_trans = cisco_type_trans; 319*1da177e4SLinus Torvalds hdlc->proto.id = IF_PROTO_CISCO; 320*1da177e4SLinus Torvalds dev->hard_start_xmit = hdlc->xmit; 321*1da177e4SLinus Torvalds dev->hard_header = cisco_hard_header; 322*1da177e4SLinus Torvalds dev->hard_header_cache = NULL; 323*1da177e4SLinus Torvalds dev->type = ARPHRD_CISCO; 324*1da177e4SLinus Torvalds dev->flags = IFF_POINTOPOINT | IFF_NOARP; 325*1da177e4SLinus Torvalds dev->addr_len = 0; 326*1da177e4SLinus Torvalds return 0; 327*1da177e4SLinus Torvalds } 328*1da177e4SLinus Torvalds 329*1da177e4SLinus Torvalds return -EINVAL; 330*1da177e4SLinus Torvalds } 331