dlci.c 11 KB

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