1 // SPDX-License-Identifier: GPL-2.0-or-later << 2 /* 1 /* >> 2 * This program is free software; you can redistribute it and/or modify >> 3 * it under the terms of the GNU General Public License as published by >> 4 * the Free Software Foundation; either version 2 of the License, or >> 5 * (at your option) any later version. 3 * 6 * 4 * Copyright Jonathan Naylor G4KLX (g4klx@g4kl 7 * Copyright Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk) 5 */ 8 */ 6 #include <linux/module.h> 9 #include <linux/module.h> 7 #include <linux/proc_fs.h> 10 #include <linux/proc_fs.h> 8 #include <linux/kernel.h> 11 #include <linux/kernel.h> 9 #include <linux/interrupt.h> 12 #include <linux/interrupt.h> 10 #include <linux/fs.h> 13 #include <linux/fs.h> 11 #include <linux/types.h> 14 #include <linux/types.h> 12 #include <linux/sysctl.h> 15 #include <linux/sysctl.h> 13 #include <linux/string.h> 16 #include <linux/string.h> 14 #include <linux/socket.h> 17 #include <linux/socket.h> 15 #include <linux/errno.h> 18 #include <linux/errno.h> 16 #include <linux/fcntl.h> 19 #include <linux/fcntl.h> 17 #include <linux/in.h> 20 #include <linux/in.h> 18 #include <linux/if_ether.h> /* For the sta 21 #include <linux/if_ether.h> /* For the statistics structure. */ 19 #include <linux/slab.h> 22 #include <linux/slab.h> 20 #include <linux/uaccess.h> 23 #include <linux/uaccess.h> 21 24 22 #include <asm/io.h> 25 #include <asm/io.h> 23 26 24 #include <linux/inet.h> 27 #include <linux/inet.h> 25 #include <linux/netdevice.h> 28 #include <linux/netdevice.h> 26 #include <linux/etherdevice.h> 29 #include <linux/etherdevice.h> 27 #include <linux/if_arp.h> 30 #include <linux/if_arp.h> 28 #include <linux/skbuff.h> 31 #include <linux/skbuff.h> 29 32 30 #include <net/ip.h> 33 #include <net/ip.h> 31 #include <net/arp.h> 34 #include <net/arp.h> 32 35 33 #include <net/ax25.h> 36 #include <net/ax25.h> 34 #include <net/netrom.h> 37 #include <net/netrom.h> 35 38 36 /* 39 /* 37 * Only allow IP over NET/ROM frames thro 40 * Only allow IP over NET/ROM frames through if the netrom device is up. 38 */ 41 */ 39 42 40 int nr_rx_ip(struct sk_buff *skb, struct net_d 43 int nr_rx_ip(struct sk_buff *skb, struct net_device *dev) 41 { 44 { 42 struct net_device_stats *stats = &dev- 45 struct net_device_stats *stats = &dev->stats; 43 46 44 if (!netif_running(dev)) { 47 if (!netif_running(dev)) { 45 stats->rx_dropped++; 48 stats->rx_dropped++; 46 return 0; 49 return 0; 47 } 50 } 48 51 49 stats->rx_packets++; 52 stats->rx_packets++; 50 stats->rx_bytes += skb->len; 53 stats->rx_bytes += skb->len; 51 54 52 skb->protocol = htons(ETH_P_IP); 55 skb->protocol = htons(ETH_P_IP); 53 56 54 /* Spoof incoming device */ 57 /* Spoof incoming device */ 55 skb->dev = dev; 58 skb->dev = dev; 56 skb->mac_header = skb->network_header; 59 skb->mac_header = skb->network_header; 57 skb_reset_network_header(skb); 60 skb_reset_network_header(skb); 58 skb->pkt_type = PACKET_HOST; 61 skb->pkt_type = PACKET_HOST; 59 62 60 netif_rx(skb); 63 netif_rx(skb); 61 64 62 return 1; 65 return 1; 63 } 66 } 64 67 65 static int nr_header(struct sk_buff *skb, stru 68 static int nr_header(struct sk_buff *skb, struct net_device *dev, 66 unsigned short type, 69 unsigned short type, 67 const void *daddr, const 70 const void *daddr, const void *saddr, unsigned int len) 68 { 71 { 69 unsigned char *buff = skb_push(skb, NR 72 unsigned char *buff = skb_push(skb, NR_NETWORK_LEN + NR_TRANSPORT_LEN); 70 73 71 memcpy(buff, (saddr != NULL) ? saddr : 74 memcpy(buff, (saddr != NULL) ? saddr : dev->dev_addr, dev->addr_len); 72 buff[6] &= ~AX25_CBIT; 75 buff[6] &= ~AX25_CBIT; 73 buff[6] &= ~AX25_EBIT; 76 buff[6] &= ~AX25_EBIT; 74 buff[6] |= AX25_SSSID_SPARE; 77 buff[6] |= AX25_SSSID_SPARE; 75 buff += AX25_ADDR_LEN; 78 buff += AX25_ADDR_LEN; 76 79 77 if (daddr != NULL) 80 if (daddr != NULL) 78 memcpy(buff, daddr, dev->addr_ 81 memcpy(buff, daddr, dev->addr_len); 79 buff[6] &= ~AX25_CBIT; 82 buff[6] &= ~AX25_CBIT; 80 buff[6] |= AX25_EBIT; 83 buff[6] |= AX25_EBIT; 81 buff[6] |= AX25_SSSID_SPARE; 84 buff[6] |= AX25_SSSID_SPARE; 82 buff += AX25_ADDR_LEN; 85 buff += AX25_ADDR_LEN; 83 86 84 *buff++ = READ_ONCE(sysctl_netrom_netw 87 *buff++ = READ_ONCE(sysctl_netrom_network_ttl_initialiser); 85 88 86 *buff++ = NR_PROTO_IP; 89 *buff++ = NR_PROTO_IP; 87 *buff++ = NR_PROTO_IP; 90 *buff++ = NR_PROTO_IP; 88 *buff++ = 0; 91 *buff++ = 0; 89 *buff++ = 0; 92 *buff++ = 0; 90 *buff++ = NR_PROTOEXT; 93 *buff++ = NR_PROTOEXT; 91 94 92 if (daddr != NULL) 95 if (daddr != NULL) 93 return 37; 96 return 37; 94 97 95 return -37; 98 return -37; 96 } 99 } 97 100 98 static int __must_check nr_set_mac_address(str 101 static int __must_check nr_set_mac_address(struct net_device *dev, void *addr) 99 { 102 { 100 struct sockaddr *sa = addr; 103 struct sockaddr *sa = addr; 101 int err; 104 int err; 102 105 103 if (!memcmp(dev->dev_addr, sa->sa_data 106 if (!memcmp(dev->dev_addr, sa->sa_data, dev->addr_len)) 104 return 0; 107 return 0; 105 108 106 if (dev->flags & IFF_UP) { 109 if (dev->flags & IFF_UP) { 107 err = ax25_listen_register((ax 110 err = ax25_listen_register((ax25_address *)sa->sa_data, NULL); 108 if (err) 111 if (err) 109 return err; 112 return err; 110 113 111 ax25_listen_release((const ax2 !! 114 ax25_listen_release((ax25_address *)dev->dev_addr, NULL); 112 } 115 } 113 116 114 dev_addr_set(dev, sa->sa_data); !! 117 memcpy(dev->dev_addr, sa->sa_data, dev->addr_len); 115 118 116 return 0; 119 return 0; 117 } 120 } 118 121 119 static int nr_open(struct net_device *dev) 122 static int nr_open(struct net_device *dev) 120 { 123 { 121 int err; 124 int err; 122 125 123 err = ax25_listen_register((const ax25 !! 126 err = ax25_listen_register((ax25_address *)dev->dev_addr, NULL); 124 if (err) 127 if (err) 125 return err; 128 return err; 126 129 127 netif_start_queue(dev); 130 netif_start_queue(dev); 128 131 129 return 0; 132 return 0; 130 } 133 } 131 134 132 static int nr_close(struct net_device *dev) 135 static int nr_close(struct net_device *dev) 133 { 136 { 134 ax25_listen_release((const ax25_addres !! 137 ax25_listen_release((ax25_address *)dev->dev_addr, NULL); 135 netif_stop_queue(dev); 138 netif_stop_queue(dev); 136 return 0; 139 return 0; 137 } 140 } 138 141 139 static netdev_tx_t nr_xmit(struct sk_buff *skb 142 static netdev_tx_t nr_xmit(struct sk_buff *skb, struct net_device *dev) 140 { 143 { 141 struct net_device_stats *stats = &dev- 144 struct net_device_stats *stats = &dev->stats; 142 unsigned int len = skb->len; 145 unsigned int len = skb->len; 143 146 144 if (!nr_route_frame(skb, NULL)) { 147 if (!nr_route_frame(skb, NULL)) { 145 kfree_skb(skb); 148 kfree_skb(skb); 146 stats->tx_errors++; 149 stats->tx_errors++; 147 return NETDEV_TX_OK; 150 return NETDEV_TX_OK; 148 } 151 } 149 152 150 stats->tx_packets++; 153 stats->tx_packets++; 151 stats->tx_bytes += len; 154 stats->tx_bytes += len; 152 155 153 return NETDEV_TX_OK; 156 return NETDEV_TX_OK; 154 } 157 } 155 158 156 static const struct header_ops nr_header_ops = 159 static const struct header_ops nr_header_ops = { 157 .create = nr_header, 160 .create = nr_header, 158 }; 161 }; 159 162 160 static const struct net_device_ops nr_netdev_o 163 static const struct net_device_ops nr_netdev_ops = { 161 .ndo_open = nr_open, 164 .ndo_open = nr_open, 162 .ndo_stop = nr_close, 165 .ndo_stop = nr_close, 163 .ndo_start_xmit = nr_xmit, 166 .ndo_start_xmit = nr_xmit, 164 .ndo_set_mac_address = nr_set_mac_a 167 .ndo_set_mac_address = nr_set_mac_address, 165 }; 168 }; 166 169 167 void nr_setup(struct net_device *dev) 170 void nr_setup(struct net_device *dev) 168 { 171 { 169 dev->mtu = NR_MAX_PACKE 172 dev->mtu = NR_MAX_PACKET_SIZE; 170 dev->netdev_ops = &nr_netdev_o 173 dev->netdev_ops = &nr_netdev_ops; 171 dev->header_ops = &nr_header_o 174 dev->header_ops = &nr_header_ops; 172 dev->hard_header_len = NR_NETWORK_L 175 dev->hard_header_len = NR_NETWORK_LEN + NR_TRANSPORT_LEN; 173 dev->addr_len = AX25_ADDR_LE 176 dev->addr_len = AX25_ADDR_LEN; 174 dev->type = ARPHRD_NETRO 177 dev->type = ARPHRD_NETROM; 175 178 176 /* New-style flags. */ 179 /* New-style flags. */ 177 dev->flags = IFF_NOARP; 180 dev->flags = IFF_NOARP; 178 } 181 } 179 182
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.