cregit-Linux how code gets into the kernel

Release 4.11 drivers/net/wan/lapbether.c

Directory: drivers/net/wan
/*
 *      "LAPB via ethernet" driver release 001
 *
 *      This code REQUIRES 2.1.15 or higher/ NET3.038
 *
 *      This module:
 *              This module is free software; you can redistribute it and/or
 *              modify it under the terms of the GNU General Public License
 *              as published by the Free Software Foundation; either version
 *              2 of the License, or (at your option) any later version.
 *
 *      This is a "pseudo" network driver to allow LAPB over Ethernet.
 *
 *      This driver can use any ethernet destination address, and can be 
 *      limited to accept frames from one dedicated ethernet card only.
 *
 *      History
 *      LAPBETH 001     Jonathan Naylor         Cloned from bpqether.c
 *      2000-10-29      Henner Eisen    lapb_data_indication() return status.
 *      2000-11-14      Henner Eisen    dev_hold/put, NETDEV_GOING_DOWN support
 */


#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include <linux/errno.h>
#include <linux/types.h>
#include <linux/socket.h>
#include <linux/in.h>
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/net.h>
#include <linux/inet.h>
#include <linux/netdevice.h>
#include <linux/if_arp.h>
#include <linux/skbuff.h>
#include <net/sock.h>
#include <linux/uaccess.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/notifier.h>
#include <linux/stat.h>
#include <linux/module.h>
#include <linux/lapb.h>
#include <linux/init.h>

#include <net/x25device.h>


static const u8 bcast_addr[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };

/* If this number is made larger, check that the temporary string buffer
 * in lapbeth_new_device is large enough to store the probe device name.*/

#define MAXLAPBDEV 100


struct lapbethdev {
	
struct list_head	node;
	
struct net_device	*ethdev;	/* link to ethernet device */
	
struct net_device	*axdev;		/* lapbeth device (lapb#) */
};

static LIST_HEAD(lapbeth_devices);

/* ------------------------------------------------------------------------ */

/*
 *      Get the LAPB device for the ethernet device
 */

static struct lapbethdev *lapbeth_get_x25_dev(struct net_device *dev) { struct lapbethdev *lapbeth; list_for_each_entry_rcu(lapbeth, &lapbeth_devices, node) { if (lapbeth->ethdev == dev) return lapbeth; } return NULL; }

Contributors

PersonTokensPropCommitsCommitProp
Stephen Hemminger2047.62%133.33%
Linus Torvalds (pre-git)1228.57%133.33%
Arnaldo Carvalho de Melo1023.81%133.33%
Total42100.00%3100.00%


static __inline__ int dev_is_ethdev(struct net_device *dev) { return dev->type == ARPHRD_ETHER && strncmp(dev->name, "dummy", 5); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)2893.33%250.00%
Arnaldo Carvalho de Melo13.33%125.00%
Stephen Hemminger13.33%125.00%
Total30100.00%4100.00%

/* ------------------------------------------------------------------------ */ /* * Receive a LAPB frame via an ethernet interface. */
static int lapbeth_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *ptype, struct net_device *orig_dev) { int len, err; struct lapbethdev *lapbeth; if (dev_net(dev) != &init_net) goto drop; if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) return NET_RX_DROP; if (!pskb_may_pull(skb, 2)) goto drop; rcu_read_lock(); lapbeth = lapbeth_get_x25_dev(dev); if (!lapbeth) goto drop_unlock; if (!netif_running(lapbeth->axdev)) goto drop_unlock; len = skb->data[0] + skb->data[1] * 256; dev->stats.rx_packets++; dev->stats.rx_bytes += len; skb_pull(skb, 2); /* Remove the length bytes */ skb_trim(skb, len); /* Set the length of the data */ if ((err = lapb_data_received(lapbeth->axdev, skb)) != LAPB_OK) { printk(KERN_DEBUG "lapbether: lapb_data_received err - %d\n", err); goto drop_unlock; } out: rcu_read_unlock(); return 0; drop_unlock: kfree_skb(skb); goto out; drop: kfree_skb(skb); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)10749.08%325.00%
David S. Miller4922.48%325.00%
Arnaldo Carvalho de Melo2411.01%18.33%
Stephen Hemminger2310.55%216.67%
Eric W. Biedermann104.59%18.33%
Hideaki Yoshifuji / 吉藤英明31.38%18.33%
Al Viro20.92%18.33%
Total218100.00%12100.00%


static int lapbeth_data_indication(struct net_device *dev, struct sk_buff *skb) { unsigned char *ptr; skb_push(skb, 1); if (skb_cow(skb, 1)) return NET_RX_DROP; ptr = skb->data; *ptr = X25_IFACE_DATA; skb->protocol = x25_type_trans(skb, dev); return netif_rx(skb); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)4261.76%233.33%
David S. Miller1826.47%116.67%
Arnaldo Carvalho de Melo45.88%116.67%
Al Viro34.41%116.67%
Andrew Hendry11.47%116.67%
Total68100.00%6100.00%

/* * Send a LAPB frame via an ethernet interface */
static netdev_tx_t lapbeth_xmit(struct sk_buff *skb, struct net_device *dev) { int err; /* * Just to be *really* sure not to send anything if the interface * is down, the ethernet device may have gone. */ if (!netif_running(dev)) goto drop; switch (skb->data[0]) { case X25_IFACE_DATA: break; case X25_IFACE_CONNECT: if ((err = lapb_connect_request(dev)) != LAPB_OK) pr_err("lapb_connect_request error: %d\n", err); goto drop; case X25_IFACE_DISCONNECT: if ((err = lapb_disconnect_request(dev)) != LAPB_OK) pr_err("lapb_disconnect_request err: %d\n", err); /* Fall thru */ default: goto drop; } skb_pull(skb, 1); if ((err = lapb_data_request(dev, skb)) != LAPB_OK) { pr_err("lapb_data_request error - %d\n", err); goto drop; } out: return NETDEV_TX_OK; drop: kfree_skb(skb); goto out; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)10671.14%436.36%
Arnaldo Carvalho de Melo2416.11%19.09%
Joe Perches64.03%19.09%
Al Viro32.01%19.09%
Patrick McHardy32.01%19.09%
Linus Torvalds32.01%19.09%
Andrew Hendry32.01%19.09%
Stephen Hemminger10.67%19.09%
Total149100.00%11100.00%


static void lapbeth_data_transmit(struct net_device *ndev, struct sk_buff *skb) { struct lapbethdev *lapbeth = netdev_priv(ndev); unsigned char *ptr; struct net_device *dev; int size = skb->len; skb->protocol = htons(ETH_P_X25); ptr = skb_push(skb, 2); *ptr++ = size % 256; *ptr++ = size / 256; ndev->stats.tx_packets++; ndev->stats.tx_bytes += size; skb->dev = dev = lapbeth->ethdev; dev_hard_header(skb, dev, ETH_P_DEC, bcast_addr, NULL, 0); dev_queue_xmit(skb); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)10182.79%440.00%
Stephen Hemminger108.20%330.00%
Al Viro43.28%110.00%
Arnaldo Carvalho de Melo43.28%110.00%
Randy Dunlap32.46%110.00%
Total122100.00%10100.00%


static void lapbeth_connected(struct net_device *dev, int reason) { unsigned char *ptr; struct sk_buff *skb = dev_alloc_skb(1); if (!skb) { pr_err("out of memory\n"); return; } ptr = skb_put(skb, 1); *ptr = X25_IFACE_CONNECT; skb->protocol = x25_type_trans(skb, dev); netif_rx(skb); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)5373.61%116.67%
Arnaldo Carvalho de Melo1318.06%233.33%
Al Viro34.17%116.67%
Joe Perches22.78%116.67%
Andrew Hendry11.39%116.67%
Total72100.00%6100.00%


static void lapbeth_disconnected(struct net_device *dev, int reason) { unsigned char *ptr; struct sk_buff *skb = dev_alloc_skb(1); if (!skb) { pr_err("out of memory\n"); return; } ptr = skb_put(skb, 1); *ptr = X25_IFACE_DISCONNECT; skb->protocol = x25_type_trans(skb, dev); netif_rx(skb); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)5170.83%116.67%
Arnaldo Carvalho de Melo1520.83%233.33%
Al Viro34.17%116.67%
Joe Perches22.78%116.67%
Andrew Hendry11.39%116.67%
Total72100.00%6100.00%

/* * Set AX.25 callsign */
static int lapbeth_set_mac_address(struct net_device *dev, void *addr) { struct sockaddr *sa = addr; memcpy(dev->dev_addr, sa->sa_data, dev->addr_len); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)40100.00%2100.00%
Total40100.00%2100.00%

static const struct lapb_register_struct lapbeth_callbacks = { .connect_confirmation = lapbeth_connected, .connect_indication = lapbeth_connected, .disconnect_confirmation = lapbeth_disconnected, .disconnect_indication = lapbeth_disconnected, .data_indication = lapbeth_data_indication, .data_transmit = lapbeth_data_transmit, }; /* * open/close a device */
static int lapbeth_open(struct net_device *dev) { int err; if ((err = lapb_register(dev, &lapbeth_callbacks)) != LAPB_OK) { pr_err("lapb_register error: %d\n", err); return -ENODEV; } netif_start_queue(dev); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)4894.12%360.00%
Joe Perches23.92%120.00%
Al Viro11.96%120.00%
Total51100.00%5100.00%


static int lapbeth_close(struct net_device *dev) { int err; netif_stop_queue(dev); if ((err = lapb_unregister(dev)) != LAPB_OK) pr_err("lapb_unregister error: %d\n", err); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)2559.52%233.33%
Stephen Hemminger716.67%116.67%
Linus Torvalds716.67%116.67%
Joe Perches24.76%116.67%
Al Viro12.38%116.67%
Total42100.00%6100.00%

/* ------------------------------------------------------------------------ */ static const struct net_device_ops lapbeth_netdev_ops = { .ndo_open = lapbeth_open, .ndo_stop = lapbeth_close, .ndo_start_xmit = lapbeth_xmit, .ndo_set_mac_address = lapbeth_set_mac_address, };
static void lapbeth_setup(struct net_device *dev) { dev->netdev_ops = &lapbeth_netdev_ops; dev->destructor = free_netdev; dev->type = ARPHRD_X25; dev->hard_header_len = 3; dev->mtu = 1000; dev->addr_len = 0; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)2858.33%125.00%
Stephen Hemminger2041.67%375.00%
Total48100.00%4100.00%

/* * Setup a new device. */
static int lapbeth_new_device(struct net_device *dev) { struct net_device *ndev; struct lapbethdev *lapbeth; int rc = -ENOMEM; ASSERT_RTNL(); ndev = alloc_netdev(sizeof(*lapbeth), "lapb%d", NET_NAME_UNKNOWN, lapbeth_setup); if (!ndev) goto out; lapbeth = netdev_priv(ndev); lapbeth->axdev = ndev; dev_hold(dev); lapbeth->ethdev = dev; rc = -EIO; if (register_netdevice(ndev)) goto fail; list_add_rcu(&lapbeth->node, &lapbeth_devices); rc = 0; out: return rc; fail: dev_put(dev); free_netdev(ndev); kfree(lapbeth); goto out; }

Contributors

PersonTokensPropCommitsCommitProp
Stephen Hemminger8865.67%116.67%
Arnaldo Carvalho de Melo3022.39%116.67%
Linus Torvalds (pre-git)64.48%116.67%
Al Viro53.73%116.67%
Randy Dunlap32.24%116.67%
Tom Gundersen21.49%116.67%
Total134100.00%6100.00%

/* * Free a lapb network device. */
static void lapbeth_free_device(struct lapbethdev *lapbeth) { dev_put(lapbeth->ethdev); list_del_rcu(&lapbeth->node); unregister_netdevice(lapbeth->axdev); }

Contributors

PersonTokensPropCommitsCommitProp
Stephen Hemminger33100.00%1100.00%
Total33100.00%1100.00%

/* * Handle device status changes. * * Called from notifier with RTNL held. */
static int lapbeth_device_event(struct notifier_block *this, unsigned long event, void *ptr) { struct lapbethdev *lapbeth; struct net_device *dev = netdev_notifier_info_to_dev(ptr); if (dev_net(dev) != &init_net) return NOTIFY_DONE; if (!dev_is_ethdev(dev)) return NOTIFY_DONE; switch (event) { case NETDEV_UP: /* New ethernet device -> new LAPB interface */ if (lapbeth_get_x25_dev(dev) == NULL) lapbeth_new_device(dev); break; case NETDEV_DOWN: /* ethernet device closed -> close LAPB interface */ lapbeth = lapbeth_get_x25_dev(dev); if (lapbeth) dev_close(lapbeth->axdev); break; case NETDEV_UNREGISTER: /* ethernet device disappears -> remove LAPB interface */ lapbeth = lapbeth_get_x25_dev(dev); if (lapbeth) lapbeth_free_device(lapbeth); break; } return NOTIFY_DONE; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)7557.69%228.57%
Stephen Hemminger2317.69%114.29%
Arnaldo Carvalho de Melo1612.31%114.29%
Eric W. Biedermann107.69%114.29%
Jiri Pirko32.31%114.29%
Hideaki Yoshifuji / 吉藤英明32.31%114.29%
Total130100.00%7100.00%

/* ------------------------------------------------------------------------ */ static struct packet_type lapbeth_packet_type __read_mostly = { .type = cpu_to_be16(ETH_P_DEC), .func = lapbeth_rcv, }; static struct notifier_block lapbeth_dev_notifier = { .notifier_call = lapbeth_device_event, }; static const char banner[] __initconst = KERN_INFO "LAPB Ethernet driver version 0.02\n";
static int __init lapbeth_init_driver(void) { dev_add_pack(&lapbeth_packet_type); register_netdevice_notifier(&lapbeth_dev_notifier); printk(banner); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)2586.21%150.00%
Linus Torvalds413.79%150.00%
Total29100.00%2100.00%

module_init(lapbeth_init_driver);
static void __exit lapbeth_cleanup_driver(void) { struct lapbethdev *lapbeth; struct list_head *entry, *tmp; dev_remove_pack(&lapbeth_packet_type); unregister_netdevice_notifier(&lapbeth_dev_notifier); rtnl_lock(); list_for_each_safe(entry, tmp, &lapbeth_devices) { lapbeth = list_entry(entry, struct lapbethdev, node); dev_put(lapbeth->ethdev); unregister_netdevice(lapbeth->axdev); } rtnl_unlock(); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)3140.79%120.00%
Arnaldo Carvalho de Melo3039.47%120.00%
David S. Miller79.21%120.00%
Stephen Hemminger56.58%120.00%
Linus Torvalds33.95%120.00%
Total76100.00%5100.00%

module_exit(lapbeth_cleanup_driver); MODULE_AUTHOR("Jonathan Naylor <g4klx@g4klx.demon.co.uk>"); MODULE_DESCRIPTION("The unofficial LAPB over Ethernet driver"); MODULE_LICENSE("GPL");

Overall Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)88954.54%1021.28%
Stephen Hemminger30618.77%1123.40%
Arnaldo Carvalho de Melo18211.17%24.26%
Linus Torvalds744.54%36.38%
David S. Miller744.54%48.51%
Al Viro251.53%36.38%
Joe Perches211.29%12.13%
Eric W. Biedermann201.23%24.26%
Andrew Hendry60.37%12.13%
Rusty Russell60.37%12.13%
Randy Dunlap60.37%12.13%
Hideaki Yoshifuji / 吉藤英明60.37%12.13%
Patrick McHardy30.18%12.13%
Tejun Heo30.18%12.13%
Jiri Pirko30.18%12.13%
Tom Gundersen20.12%12.13%
Robert P. J. Day20.12%12.13%
Harvey Harrison10.06%12.13%
Hannes Eder10.06%12.13%
Total1630100.00%47100.00%
Directory: drivers/net/wan
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.