11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or modify 31da177e4SLinus Torvalds * it under the terms of the GNU General Public License as published by 41da177e4SLinus Torvalds * the Free Software Foundation; either version 2 of the License, or 51da177e4SLinus Torvalds * (at your option) any later version. 61da177e4SLinus Torvalds * 71da177e4SLinus Torvalds * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk) 81da177e4SLinus Torvalds */ 91da177e4SLinus Torvalds #include <linux/module.h> 101da177e4SLinus Torvalds #include <linux/proc_fs.h> 111da177e4SLinus Torvalds #include <linux/kernel.h> 121da177e4SLinus Torvalds #include <linux/interrupt.h> 131da177e4SLinus Torvalds #include <linux/fs.h> 141da177e4SLinus Torvalds #include <linux/types.h> 151da177e4SLinus Torvalds #include <linux/sysctl.h> 161da177e4SLinus Torvalds #include <linux/string.h> 171da177e4SLinus Torvalds #include <linux/socket.h> 181da177e4SLinus Torvalds #include <linux/errno.h> 191da177e4SLinus Torvalds #include <linux/fcntl.h> 201da177e4SLinus Torvalds #include <linux/in.h> 211da177e4SLinus Torvalds #include <linux/if_ether.h> 225a0e3ad6STejun Heo #include <linux/slab.h> 231da177e4SLinus Torvalds 241da177e4SLinus Torvalds #include <asm/system.h> 251da177e4SLinus Torvalds #include <asm/io.h> 261da177e4SLinus Torvalds 271da177e4SLinus Torvalds #include <linux/inet.h> 281da177e4SLinus Torvalds #include <linux/netdevice.h> 291da177e4SLinus Torvalds #include <linux/etherdevice.h> 301da177e4SLinus Torvalds #include <linux/if_arp.h> 311da177e4SLinus Torvalds #include <linux/skbuff.h> 321da177e4SLinus Torvalds 331da177e4SLinus Torvalds #include <net/ip.h> 341da177e4SLinus Torvalds #include <net/arp.h> 351da177e4SLinus Torvalds 361da177e4SLinus Torvalds #include <net/ax25.h> 371da177e4SLinus Torvalds #include <net/rose.h> 381da177e4SLinus Torvalds 393b04dddeSStephen Hemminger static int rose_header(struct sk_buff *skb, struct net_device *dev, 403b04dddeSStephen Hemminger unsigned short type, 413b04dddeSStephen Hemminger const void *daddr, const void *saddr, unsigned len) 421da177e4SLinus Torvalds { 431da177e4SLinus Torvalds unsigned char *buff = skb_push(skb, ROSE_MIN_LEN + 2); 441da177e4SLinus Torvalds 451da177e4SLinus Torvalds *buff++ = ROSE_GFI | ROSE_Q_BIT; 461da177e4SLinus Torvalds *buff++ = 0x00; 471da177e4SLinus Torvalds *buff++ = ROSE_DATA; 481da177e4SLinus Torvalds *buff++ = 0x7F; 491da177e4SLinus Torvalds *buff++ = AX25_P_IP; 501da177e4SLinus Torvalds 511da177e4SLinus Torvalds if (daddr != NULL) 521da177e4SLinus Torvalds return 37; 531da177e4SLinus Torvalds 541da177e4SLinus Torvalds return -37; 551da177e4SLinus Torvalds } 561da177e4SLinus Torvalds 571da177e4SLinus Torvalds static int rose_rebuild_header(struct sk_buff *skb) 581da177e4SLinus Torvalds { 5978f150bfSPavel Emelyanov #ifdef CONFIG_INET 601da177e4SLinus Torvalds struct net_device *dev = skb->dev; 61d289d120SStephen Hemminger struct net_device_stats *stats = &dev->stats; 621da177e4SLinus Torvalds unsigned char *bp = (unsigned char *)skb->data; 631da177e4SLinus Torvalds struct sk_buff *skbn; 648dc22d2bSRalf Baechle unsigned int len; 651da177e4SLinus Torvalds 661da177e4SLinus Torvalds if (arp_find(bp + 7, skb)) { 671da177e4SLinus Torvalds return 1; 681da177e4SLinus Torvalds } 691da177e4SLinus Torvalds 701da177e4SLinus Torvalds if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) { 711da177e4SLinus Torvalds kfree_skb(skb); 721da177e4SLinus Torvalds return 1; 731da177e4SLinus Torvalds } 741da177e4SLinus Torvalds 751da177e4SLinus Torvalds if (skb->sk != NULL) 761da177e4SLinus Torvalds skb_set_owner_w(skbn, skb->sk); 771da177e4SLinus Torvalds 781da177e4SLinus Torvalds kfree_skb(skb); 791da177e4SLinus Torvalds 808dc22d2bSRalf Baechle len = skbn->len; 818dc22d2bSRalf Baechle 821da177e4SLinus Torvalds if (!rose_route_frame(skbn, NULL)) { 831da177e4SLinus Torvalds kfree_skb(skbn); 841da177e4SLinus Torvalds stats->tx_errors++; 851da177e4SLinus Torvalds return 1; 861da177e4SLinus Torvalds } 871da177e4SLinus Torvalds 881da177e4SLinus Torvalds stats->tx_packets++; 898dc22d2bSRalf Baechle stats->tx_bytes += len; 901da177e4SLinus Torvalds #endif 911da177e4SLinus Torvalds return 1; 921da177e4SLinus Torvalds } 931da177e4SLinus Torvalds 941da177e4SLinus Torvalds static int rose_set_mac_address(struct net_device *dev, void *addr) 951da177e4SLinus Torvalds { 961da177e4SLinus Torvalds struct sockaddr *sa = addr; 97a159aaa3SRalf Baechle int err; 98a159aaa3SRalf Baechle 99*81213b5eSdanborkmann@iogearbox.net if (!memcmp(dev->dev_addr, sa->sa_data, dev->addr_len)) 100a159aaa3SRalf Baechle return 0; 101a159aaa3SRalf Baechle 102a159aaa3SRalf Baechle if (dev->flags & IFF_UP) { 103*81213b5eSdanborkmann@iogearbox.net err = rose_add_loopback_node((rose_address *)sa->sa_data); 104a159aaa3SRalf Baechle if (err) 105a159aaa3SRalf Baechle return err; 1061da177e4SLinus Torvalds 1071da177e4SLinus Torvalds rose_del_loopback_node((rose_address *)dev->dev_addr); 108a159aaa3SRalf Baechle } 1091da177e4SLinus Torvalds 1101da177e4SLinus Torvalds memcpy(dev->dev_addr, sa->sa_data, dev->addr_len); 1111da177e4SLinus Torvalds 1121da177e4SLinus Torvalds return 0; 1131da177e4SLinus Torvalds } 1141da177e4SLinus Torvalds 1151da177e4SLinus Torvalds static int rose_open(struct net_device *dev) 1161da177e4SLinus Torvalds { 117a159aaa3SRalf Baechle int err; 118a159aaa3SRalf Baechle 119a159aaa3SRalf Baechle err = rose_add_loopback_node((rose_address *)dev->dev_addr); 120a159aaa3SRalf Baechle if (err) 121a159aaa3SRalf Baechle return err; 122a159aaa3SRalf Baechle 1231da177e4SLinus Torvalds netif_start_queue(dev); 124a159aaa3SRalf Baechle 1251da177e4SLinus Torvalds return 0; 1261da177e4SLinus Torvalds } 1271da177e4SLinus Torvalds 1281da177e4SLinus Torvalds static int rose_close(struct net_device *dev) 1291da177e4SLinus Torvalds { 1301da177e4SLinus Torvalds netif_stop_queue(dev); 1311da177e4SLinus Torvalds rose_del_loopback_node((rose_address *)dev->dev_addr); 1321da177e4SLinus Torvalds return 0; 1331da177e4SLinus Torvalds } 1341da177e4SLinus Torvalds 13536e4d64aSStephen Hemminger static netdev_tx_t rose_xmit(struct sk_buff *skb, struct net_device *dev) 1361da177e4SLinus Torvalds { 137d289d120SStephen Hemminger struct net_device_stats *stats = &dev->stats; 1381da177e4SLinus Torvalds 1391da177e4SLinus Torvalds if (!netif_running(dev)) { 1401da177e4SLinus Torvalds printk(KERN_ERR "ROSE: rose_xmit - called when iface is down\n"); 1415b548140SPatrick McHardy return NETDEV_TX_BUSY; 1421da177e4SLinus Torvalds } 1431da177e4SLinus Torvalds dev_kfree_skb(skb); 1441da177e4SLinus Torvalds stats->tx_errors++; 1456ed10654SPatrick McHardy return NETDEV_TX_OK; 1461da177e4SLinus Torvalds } 1471da177e4SLinus Torvalds 1483b04dddeSStephen Hemminger static const struct header_ops rose_header_ops = { 1493b04dddeSStephen Hemminger .create = rose_header, 1503b04dddeSStephen Hemminger .rebuild= rose_rebuild_header, 1513b04dddeSStephen Hemminger }; 1523b04dddeSStephen Hemminger 1533170c656SStephen Hemminger static const struct net_device_ops rose_netdev_ops = { 1543170c656SStephen Hemminger .ndo_open = rose_open, 1553170c656SStephen Hemminger .ndo_stop = rose_close, 1563170c656SStephen Hemminger .ndo_start_xmit = rose_xmit, 1573170c656SStephen Hemminger .ndo_set_mac_address = rose_set_mac_address, 1583170c656SStephen Hemminger }; 1593170c656SStephen Hemminger 1601da177e4SLinus Torvalds void rose_setup(struct net_device *dev) 1611da177e4SLinus Torvalds { 1621da177e4SLinus Torvalds dev->mtu = ROSE_MAX_PACKET_SIZE - 2; 1633170c656SStephen Hemminger dev->netdev_ops = &rose_netdev_ops; 1641da177e4SLinus Torvalds 1653b04dddeSStephen Hemminger dev->header_ops = &rose_header_ops; 1661da177e4SLinus Torvalds dev->hard_header_len = AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + ROSE_MIN_LEN; 1671da177e4SLinus Torvalds dev->addr_len = ROSE_ADDR_LEN; 1681da177e4SLinus Torvalds dev->type = ARPHRD_ROSE; 1691da177e4SLinus Torvalds 1701da177e4SLinus Torvalds /* New-style flags. */ 171d2ce4bc3SRalf Baechle dev->flags = IFF_NOARP; 1721da177e4SLinus Torvalds } 173