1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * DLCI Implementation of Frame Relay protocol for Linux, according to 4 * RFC 1490. This generic device provides en/decapsulation for an 5 * underlying hardware driver. Routes & IPs are assigned to these 6 * interfaces. Requires 'dlcicfg' program to create usable 7 * interfaces, the initial one, 'dlci' is for IOCTL use only. 8 * 9 * Version: @(#)dlci.c 0.35 4 Jan 1997 10 * 11 * Author: Mike McLagan <mike.mclagan@linux.org> 12 * 13 * Changes: 14 * 15 * 0.15 Mike Mclagan Packet freeing, bug in kmalloc call 16 * DLCI_RET handling 17 * 0.20 Mike McLagan More conservative on which packets 18 * are returned for retry and which are 19 * are dropped. If DLCI_RET_DROP is 20 * returned from the FRAD, the packet is 21 * sent back to Linux for re-transmission 22 * 0.25 Mike McLagan Converted to use SIOC IOCTL calls 23 * 0.30 Jim Freeman Fixed to allow IPX traffic 24 * 0.35 Michael Elizabeth Fixed incorrect memcpy_fromfs 25 */ 26 27#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 28 29#include <linux/module.h> 30#include <linux/kernel.h> 31#include <linux/types.h> 32#include <linux/fcntl.h> 33#include <linux/interrupt.h> 34#include <linux/ptrace.h> 35#include <linux/ioport.h> 36#include <linux/in.h> 37#include <linux/init.h> 38#include <linux/slab.h> 39#include <linux/string.h> 40#include <linux/errno.h> 41#include <linux/netdevice.h> 42#include <linux/skbuff.h> 43#include <linux/if_arp.h> 44#include <linux/if_frad.h> 45#include <linux/bitops.h> 46 47#include <net/sock.h> 48 49#include <asm/io.h> 50#include <asm/dma.h> 51#include <linux/uaccess.h> 52 53static const char version[] = "DLCI driver v0.35, 4 Jan 1997, mike.mclagan@linux.org"; 54 55static LIST_HEAD(dlci_devs); 56 57static void dlci_setup(struct net_device *); 58 59/* 60 * these encapsulate the RFC 1490 requirements as well as 61 * deal with packet transmission and reception, working with 62 * the upper network layers 63 */ 64 65static int dlci_header(struct sk_buff *skb, struct net_device *dev, 66 unsigned short type, const void *daddr, 67 const void *saddr, unsigned len) 68{ 69 struct frhdr hdr; 70 unsigned int hlen; 71 char *dest; 72 73 hdr.control = FRAD_I_UI; 74 switch (type) 75 { 76 case ETH_P_IP: 77 hdr.IP_NLPID = FRAD_P_IP; 78 hlen = sizeof(hdr.control) + sizeof(hdr.IP_NLPID); 79 break; 80 81 /* feel free to add other types, if necessary */ 82 83 default: 84 hdr.pad = FRAD_P_PADDING; 85 hdr.NLPID = FRAD_P_SNAP; 86 memset(hdr.OUI, 0, sizeof(hdr.OUI)); 87 hdr.PID = htons(type); 88 hlen = sizeof(hdr); 89 break; 90 } 91 92 dest = skb_push(skb, hlen); 93 if (!dest) 94 return 0; 95 96 memcpy(dest, &hdr, hlen); 97 98 return hlen; 99} 100 101static void dlci_receive(struct sk_buff *skb, struct net_device *dev) 102{ 103 struct frhdr *hdr; 104 int process, header; 105 106 if (!pskb_may_pull(skb, sizeof(*hdr))) { 107 netdev_notice(dev, "invalid data no header\n"); 108 dev->stats.rx_errors++; 109 kfree_skb(skb); 110 return; 111 } 112 113 hdr = (struct frhdr *) skb->data; 114 process = 0; 115 header = 0; 116 skb->dev = dev; 117 118 if (hdr->control != FRAD_I_UI) 119 { 120 netdev_notice(dev, "Invalid header flag 0x%02X\n", 121 hdr->control); 122 dev->stats.rx_errors++; 123 } 124 else 125 switch (hdr->IP_NLPID) 126 { 127 case FRAD_P_PADDING: 128 if (hdr->NLPID != FRAD_P_SNAP) 129 { 130 netdev_notice(dev, "Unsupported NLPID 0x%02X\n", 131 hdr->NLPID); 132 dev->stats.rx_errors++; 133 break; 134 } 135 136 if (hdr->OUI[0] + hdr->OUI[1] + hdr->OUI[2] != 0) 137 { 138 netdev_notice(dev, "Unsupported organizationally unique identifier 0x%02X-%02X-%02X\n", 139 hdr->OUI[0], 140 hdr->OUI[1], 141 hdr->OUI[2]); 142 dev->stats.rx_errors++; 143 break; 144 } 145 146 /* at this point, it's an EtherType frame */ 147 header = sizeof(struct frhdr); 148 /* Already in network order ! */ 149 skb->protocol = hdr->PID; 150 process = 1; 151 break; 152 153 case FRAD_P_IP: 154 header = sizeof(hdr->control) + sizeof(hdr->IP_NLPID); 155 skb->protocol = htons(ETH_P_IP); 156 process = 1; 157 break; 158 159 case FRAD_P_SNAP: 160 case FRAD_P_Q933: 161 case FRAD_P_CLNP: 162 netdev_notice(dev, "Unsupported NLPID 0x%02X\n", 163 hdr->pad); 164 dev->stats.rx_errors++; 165 break; 166 167 default: 168 netdev_notice(dev, "Invalid pad byte 0x%02X\n", 169 hdr->pad); 170 dev->stats.rx_errors++; 171 break; 172 } 173 174 if (process) 175 { 176 /* we've set up the protocol, so discard the header */ 177 skb_reset_mac_header(skb); 178 skb_pull(skb, header); 179 dev->stats.rx_bytes += skb->len; 180 netif_rx(skb); 181 dev->stats.rx_packets++; 182 } 183 else 184 dev_kfree_skb(skb); 185} 186 187static netdev_tx_t dlci_transmit(struct sk_buff *skb, struct net_device *dev) 188{ 189 struct dlci_local *dlp = netdev_priv(dev); 190 191 if (skb) { 192 struct netdev_queue *txq = skb_get_tx_queue(dev, skb); 193 netdev_start_xmit(skb, dlp->slave, txq, false); 194 } 195 return NETDEV_TX_OK; 196} 197 198static int dlci_config(struct net_device *dev, struct dlci_conf __user *conf, int get) 199{ 200 struct dlci_conf config; 201 struct dlci_local *dlp; 202 struct frad_local *flp; 203 int err; 204 205 dlp = netdev_priv(dev); 206 207 flp = netdev_priv(dlp->slave); 208 209 if (!get) 210 { 211 if (copy_from_user(&config, conf, sizeof(struct dlci_conf))) 212 return -EFAULT; 213 if (config.flags & ~DLCI_VALID_FLAGS) 214 return -EINVAL; 215 memcpy(&dlp->config, &config, sizeof(struct dlci_conf)); 216 dlp->configured = 1; 217 } 218 219 err = (*flp->dlci_conf)(dlp->slave, dev, get); 220 if (err) 221 return err; 222 223 if (get) 224 { 225 if (copy_to_user(conf, &dlp->config, sizeof(struct dlci_conf))) 226 return -EFAULT; 227 } 228 229 return 0; 230} 231 232static int dlci_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) 233{ 234 struct dlci_local *dlp; 235 236 if (!capable(CAP_NET_ADMIN)) 237 return -EPERM; 238 239 dlp = netdev_priv(dev); 240 241 switch (cmd) 242 { 243 case DLCI_GET_SLAVE: 244 if (!*(short *)(dev->dev_addr)) 245 return -EINVAL; 246 247 strncpy(ifr->ifr_slave, dlp->slave->name, sizeof(ifr->ifr_slave)); 248 break; 249 250 case DLCI_GET_CONF: 251 case DLCI_SET_CONF: 252 if (!*(short *)(dev->dev_addr)) 253 return -EINVAL; 254 255 return dlci_config(dev, ifr->ifr_data, cmd == DLCI_GET_CONF); 256 257 default: 258 return -EOPNOTSUPP; 259 } 260 return 0; 261} 262 263static int dlci_change_mtu(struct net_device *dev, int new_mtu) 264{ 265 struct dlci_local *dlp = netdev_priv(dev); 266 267 return dev_set_mtu(dlp->slave, new_mtu); 268} 269 270static int dlci_open(struct net_device *dev) 271{ 272 struct dlci_local *dlp; 273 struct frad_local *flp; 274 int err; 275 276 dlp = netdev_priv(dev); 277 278 if (!*(short *)(dev->dev_addr)) 279 return -EINVAL; 280 281 if (!netif_running(dlp->slave)) 282 return -ENOTCONN; 283 284 flp = netdev_priv(dlp->slave); 285 err = (*flp->activate)(dlp->slave, dev); 286 if (err) 287 return err; 288 289 netif_start_queue(dev); 290 291 return 0; 292} 293 294static int dlci_close(struct net_device *dev) 295{ 296 struct dlci_local *dlp; 297 struct frad_local *flp; 298 299 netif_stop_queue(dev); 300 301 dlp = netdev_priv(dev); 302 303 flp = netdev_priv(dlp->slave); 304 (*flp->deactivate)(dlp->slave, dev); 305 306 return 0; 307} 308 309static int dlci_add(struct dlci_add *dlci) 310{ 311 struct net_device *master, *slave; 312 struct dlci_local *dlp; 313 struct frad_local *flp; 314 int err = -EINVAL; 315 316 317 /* validate slave device */ 318 slave = dev_get_by_name(&init_net, dlci->devname); 319 if (!slave) 320 return -ENODEV; 321 322 if (slave->type != ARPHRD_FRAD || netdev_priv(slave) == NULL) 323 goto err1; 324 325 /* create device name */ 326 master = alloc_netdev(sizeof(struct dlci_local), "dlci%d", 327 NET_NAME_UNKNOWN, dlci_setup); 328 if (!master) { 329 err = -ENOMEM; 330 goto err1; 331 } 332 333 /* make sure same slave not already registered */ 334 rtnl_lock(); 335 list_for_each_entry(dlp, &dlci_devs, list) { 336 if (dlp->slave == slave) { 337 err = -EBUSY; 338 goto err2; 339 } 340 } 341 342 *(short *)(master->dev_addr) = dlci->dlci; 343 344 dlp = netdev_priv(master); 345 dlp->slave = slave; 346 dlp->master = master; 347 348 flp = netdev_priv(slave); 349 err = (*flp->assoc)(slave, master); 350 if (err < 0) 351 goto err2; 352 353 err = register_netdevice(master); 354 if (err < 0) 355 goto err2; 356 357 strcpy(dlci->devname, master->name); 358 359 list_add(&dlp->list, &dlci_devs); 360 rtnl_unlock(); 361 362 return 0; 363 364 err2: 365 rtnl_unlock(); 366 free_netdev(master); 367 err1: 368 dev_put(slave); 369 return err; 370} 371 372static int dlci_del(struct dlci_add *dlci) 373{ 374 struct dlci_local *dlp; 375 struct frad_local *flp; 376 struct net_device *master, *slave; 377 int err; 378 bool found = false; 379 380 rtnl_lock(); 381 382 /* validate slave device */ 383 master = __dev_get_by_name(&init_net, dlci->devname); 384 if (!master) { 385 err = -ENODEV; 386 goto out; 387 } 388 389 list_for_each_entry(dlp, &dlci_devs, list) { 390 if (dlp->master == master) { 391 found = true; 392 break; 393 } 394 } 395 if (!found) { 396 err = -ENODEV; 397 goto out; 398 } 399 400 if (netif_running(master)) { 401 err = -EBUSY; 402 goto out; 403 } 404 405 dlp = netdev_priv(master); 406 slave = dlp->slave; 407 flp = netdev_priv(slave); 408 409 err = (*flp->deassoc)(slave, master); 410 if (!err) { 411 list_del(&dlp->list); 412 413 unregister_netdevice(master); 414 415 dev_put(slave); 416 } 417out: 418 rtnl_unlock(); 419 return err; 420} 421 422static int dlci_ioctl(unsigned int cmd, void __user *arg) 423{ 424 struct dlci_add add; 425 int err; 426 427 if (!capable(CAP_NET_ADMIN)) 428 return -EPERM; 429 430 if (copy_from_user(&add, arg, sizeof(struct dlci_add))) 431 return -EFAULT; 432 433 switch (cmd) 434 { 435 case SIOCADDDLCI: 436 err = dlci_add(&add); 437 438 if (!err) 439 if (copy_to_user(arg, &add, sizeof(struct dlci_add))) 440 return -EFAULT; 441 break; 442 443 case SIOCDELDLCI: 444 err = dlci_del(&add); 445 break; 446 447 default: 448 err = -EINVAL; 449 } 450 451 return err; 452} 453 454static const struct header_ops dlci_header_ops = { 455 .create = dlci_header, 456}; 457 458static const struct net_device_ops dlci_netdev_ops = { 459 .ndo_open = dlci_open, 460 .ndo_stop = dlci_close, 461 .ndo_do_ioctl = dlci_dev_ioctl, 462 .ndo_start_xmit = dlci_transmit, 463 .ndo_change_mtu = dlci_change_mtu, 464}; 465 466static void dlci_setup(struct net_device *dev) 467{ 468 struct dlci_local *dlp = netdev_priv(dev); 469 470 dev->flags = 0; 471 dev->header_ops = &dlci_header_ops; 472 dev->netdev_ops = &dlci_netdev_ops; 473 dev->needs_free_netdev = true; 474 475 dlp->receive = dlci_receive; 476 477 dev->type = ARPHRD_DLCI; 478 dev->hard_header_len = sizeof(struct frhdr); 479 dev->addr_len = sizeof(short); 480 481} 482 483/* if slave is unregistering, then cleanup master */ 484static int dlci_dev_event(struct notifier_block *unused, 485 unsigned long event, void *ptr) 486{ 487 struct net_device *dev = netdev_notifier_info_to_dev(ptr); 488 489 if (dev_net(dev) != &init_net) 490 return NOTIFY_DONE; 491 492 if (event == NETDEV_UNREGISTER) { 493 struct dlci_local *dlp; 494 495 list_for_each_entry(dlp, &dlci_devs, list) { 496 if (dlp->slave == dev) { 497 list_del(&dlp->list); 498 unregister_netdevice(dlp->master); 499 dev_put(dlp->slave); 500 break; 501 } 502 } 503 } 504 return NOTIFY_DONE; 505} 506 507static struct notifier_block dlci_notifier = { 508 .notifier_call = dlci_dev_event, 509}; 510 511static int __init init_dlci(void) 512{ 513 dlci_ioctl_set(dlci_ioctl); 514 register_netdevice_notifier(&dlci_notifier); 515 516 printk("%s.\n", version); 517 518 return 0; 519} 520 521static void __exit dlci_exit(void) 522{ 523 struct dlci_local *dlp, *nxt; 524 525 dlci_ioctl_set(NULL); 526 unregister_netdevice_notifier(&dlci_notifier); 527 528 rtnl_lock(); 529 list_for_each_entry_safe(dlp, nxt, &dlci_devs, list) { 530 unregister_netdevice(dlp->master); 531 dev_put(dlp->slave); 532 } 533 rtnl_unlock(); 534} 535 536module_init(init_dlci); 537module_exit(dlci_exit); 538 539MODULE_AUTHOR("Mike McLagan"); 540MODULE_DESCRIPTION("Frame Relay DLCI layer"); 541MODULE_LICENSE("GPL"); 542