powerpc/perf/hv-24x7: Move cpumask file to top folder of hv-24x7 driver
[linux-2.6-microblaze.git] / drivers / net / wan / dlci.c
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
53 static const char version[] = "DLCI driver v0.35, 4 Jan 1997, mike.mclagan@linux.org";
54
55 static LIST_HEAD(dlci_devs);
56
57 static 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
65 static 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
101 static 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
187 static 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
198 static 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
232 static 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
263 static 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
270 static 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
294 static int dlci_close(struct net_device *dev)
295 {
296         struct dlci_local       *dlp;
297         struct frad_local       *flp;
298         int                     err;
299
300         netif_stop_queue(dev);
301
302         dlp = netdev_priv(dev);
303
304         flp = netdev_priv(dlp->slave);
305         err = (*flp->deactivate)(dlp->slave, dev);
306
307         return 0;
308 }
309
310 static int dlci_add(struct dlci_add *dlci)
311 {
312         struct net_device       *master, *slave;
313         struct dlci_local       *dlp;
314         struct frad_local       *flp;
315         int                     err = -EINVAL;
316
317
318         /* validate slave device */
319         slave = dev_get_by_name(&init_net, dlci->devname);
320         if (!slave)
321                 return -ENODEV;
322
323         if (slave->type != ARPHRD_FRAD || netdev_priv(slave) == NULL)
324                 goto err1;
325
326         /* create device name */
327         master = alloc_netdev(sizeof(struct dlci_local), "dlci%d",
328                               NET_NAME_UNKNOWN, dlci_setup);
329         if (!master) {
330                 err = -ENOMEM;
331                 goto err1;
332         }
333
334         /* make sure same slave not already registered */
335         rtnl_lock();
336         list_for_each_entry(dlp, &dlci_devs, list) {
337                 if (dlp->slave == slave) {
338                         err = -EBUSY;
339                         goto err2;
340                 }
341         }
342
343         *(short *)(master->dev_addr) = dlci->dlci;
344
345         dlp = netdev_priv(master);
346         dlp->slave = slave;
347         dlp->master = master;
348
349         flp = netdev_priv(slave);
350         err = (*flp->assoc)(slave, master);
351         if (err < 0)
352                 goto err2;
353
354         err = register_netdevice(master);
355         if (err < 0) 
356                 goto err2;
357
358         strcpy(dlci->devname, master->name);
359
360         list_add(&dlp->list, &dlci_devs);
361         rtnl_unlock();
362
363         return 0;
364
365  err2:
366         rtnl_unlock();
367         free_netdev(master);
368  err1:
369         dev_put(slave);
370         return err;
371 }
372
373 static int dlci_del(struct dlci_add *dlci)
374 {
375         struct dlci_local       *dlp;
376         struct frad_local       *flp;
377         struct net_device       *master, *slave;
378         int                     err;
379         bool                    found = false;
380
381         rtnl_lock();
382
383         /* validate slave device */
384         master = __dev_get_by_name(&init_net, dlci->devname);
385         if (!master) {
386                 err = -ENODEV;
387                 goto out;
388         }
389
390         list_for_each_entry(dlp, &dlci_devs, list) {
391                 if (dlp->master == master) {
392                         found = true;
393                         break;
394                 }
395         }
396         if (!found) {
397                 err = -ENODEV;
398                 goto out;
399         }
400
401         if (netif_running(master)) {
402                 err = -EBUSY;
403                 goto out;
404         }
405
406         dlp = netdev_priv(master);
407         slave = dlp->slave;
408         flp = netdev_priv(slave);
409
410         err = (*flp->deassoc)(slave, master);
411         if (!err) {
412                 list_del(&dlp->list);
413
414                 unregister_netdevice(master);
415
416                 dev_put(slave);
417         }
418 out:
419         rtnl_unlock();
420         return err;
421 }
422
423 static int dlci_ioctl(unsigned int cmd, void __user *arg)
424 {
425         struct dlci_add add;
426         int err;
427         
428         if (!capable(CAP_NET_ADMIN))
429                 return -EPERM;
430
431         if (copy_from_user(&add, arg, sizeof(struct dlci_add)))
432                 return -EFAULT;
433
434         switch (cmd)
435         {
436                 case SIOCADDDLCI:
437                         err = dlci_add(&add);
438
439                         if (!err)
440                                 if (copy_to_user(arg, &add, sizeof(struct dlci_add)))
441                                         return -EFAULT;
442                         break;
443
444                 case SIOCDELDLCI:
445                         err = dlci_del(&add);
446                         break;
447
448                 default:
449                         err = -EINVAL;
450         }
451
452         return err;
453 }
454
455 static const struct header_ops dlci_header_ops = {
456         .create = dlci_header,
457 };
458
459 static const struct net_device_ops dlci_netdev_ops = {
460         .ndo_open       = dlci_open,
461         .ndo_stop       = dlci_close,
462         .ndo_do_ioctl   = dlci_dev_ioctl,
463         .ndo_start_xmit = dlci_transmit,
464         .ndo_change_mtu = dlci_change_mtu,
465 };
466
467 static void dlci_setup(struct net_device *dev)
468 {
469         struct dlci_local *dlp = netdev_priv(dev);
470
471         dev->flags              = 0;
472         dev->header_ops         = &dlci_header_ops;
473         dev->netdev_ops         = &dlci_netdev_ops;
474         dev->needs_free_netdev  = true;
475
476         dlp->receive            = dlci_receive;
477
478         dev->type               = ARPHRD_DLCI;
479         dev->hard_header_len    = sizeof(struct frhdr);
480         dev->addr_len           = sizeof(short);
481
482 }
483
484 /* if slave is unregistering, then cleanup master */
485 static int dlci_dev_event(struct notifier_block *unused,
486                           unsigned long event, void *ptr)
487 {
488         struct net_device *dev = netdev_notifier_info_to_dev(ptr);
489
490         if (dev_net(dev) != &init_net)
491                 return NOTIFY_DONE;
492
493         if (event == NETDEV_UNREGISTER) {
494                 struct dlci_local *dlp;
495
496                 list_for_each_entry(dlp, &dlci_devs, list) {
497                         if (dlp->slave == dev) {
498                                 list_del(&dlp->list);
499                                 unregister_netdevice(dlp->master);
500                                 dev_put(dlp->slave);
501                                 break;
502                         }
503                 }
504         }
505         return NOTIFY_DONE;
506 }
507
508 static struct notifier_block dlci_notifier = {
509         .notifier_call = dlci_dev_event,
510 };
511
512 static int __init init_dlci(void)
513 {
514         dlci_ioctl_set(dlci_ioctl);
515         register_netdevice_notifier(&dlci_notifier);
516
517         printk("%s.\n", version);
518
519         return 0;
520 }
521
522 static void __exit dlci_exit(void)
523 {
524         struct dlci_local       *dlp, *nxt;
525         
526         dlci_ioctl_set(NULL);
527         unregister_netdevice_notifier(&dlci_notifier);
528
529         rtnl_lock();
530         list_for_each_entry_safe(dlp, nxt, &dlci_devs, list) {
531                 unregister_netdevice(dlp->master);
532                 dev_put(dlp->slave);
533         }
534         rtnl_unlock();
535 }
536
537 module_init(init_dlci);
538 module_exit(dlci_exit);
539
540 MODULE_AUTHOR("Mike McLagan");
541 MODULE_DESCRIPTION("Frame Relay DLCI layer");
542 MODULE_LICENSE("GPL");