summaryrefslogtreecommitdiffstats
path: root/net/ax25/ax25_netlink.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ax25/ax25_netlink.c')
-rw-r--r--net/ax25/ax25_netlink.c110
1 files changed, 110 insertions, 0 deletions
diff --git a/net/ax25/ax25_netlink.c b/net/ax25/ax25_netlink.c
new file mode 100644
index 000000000..73e25e234
--- /dev/null
+++ b/net/ax25/ax25_netlink.c
@@ -0,0 +1,110 @@
+/*
+ * ax25_netlink.c: NETLINK interface for NEW-AX.25
+ *
+ * Authors: Jens David (DG1KJD), Matthias Welwarsky (DG2FEF), Jonathan (
+ * Alan Cox (GW4PTS), Joerg (DL1BKE), et al
+ *
+ * Comment: It is intended to develop a new AX.25 routing daemon using t
+ * method to communicate with the kernel part. Recent developme
+ * Linux' realtime abilities, however, suggest removing AX.25 c
+ * from kernel space.
+ *
+ * Changelog:
+ *
+ * License: 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.
+*/
+
+#include <linux/skbuff.h>
+#include <linux/netlink.h>
+#include <linux/ax25.h>
+#include <net/sock.h>
+#include <net/ax25.h>
+
+#include "ax25_netlink.h"
+#include "ax25_route.h"
+
+static struct sock *axrtnl;
+
+static void ax25_netlink_rcv(struct sock *sk, int len)
+{
+ struct ax25_nlmsg *nlmsg;
+ struct sk_buff *skb;
+ struct net_device *dev;
+
+ while ((skb = skb_dequeue(&sk->receive_queue)) != NULL) {
+ if (skb->len < sizeof(struct ax25_nlmsg)) {
+ kfree_skb(skb);
+ break;
+ }
+ nlmsg = (struct ax25_nlmsg *)skb->data;
+
+ switch (nlmsg->msg_type) {
+ case AX25_MSG_SETRT:
+ if ((dev = dev_get(nlmsg->msg.pathmsg.port_name)) != NULL
+ && nlmsg->msg.pathmsg.path.dcount <= AX25_MAX_DIGIS)
+ ax25_add_route(&nlmsg->msg.pathmsg.path, dev);
+ break;
+
+ case AX25_MSG_DELRT:
+ if ((dev = dev_get(nlmsg->msg.pathmsg.port_name)) != NULL)
+ ax25_del_route(&nlmsg->msg.pathmsg.path.addr);
+ break;
+
+ case AX25_MSG_OPTRT:
+ if ((dev = dev_get(nlmsg->msg.pathmsg.port_name)) != NULL
+ && nlmsg->msg.pathmsg.path.dcount <= AX25_MAX_DIGIS)
+ {
+ ax25_add_route(&nlmsg->msg.pathmsg.path, dev);
+ ax25_ipopt_route(&nlmsg->msg.pathmsg.path.addr, nlmsg->msg.pathmsg.mode);
+ }
+ }
+ kfree_skb(skb);
+ }
+}
+
+void ax25_nlpost_route(ax25_pktinfo *pkt, struct net_device *dev)
+{
+ struct ax25_nlmsg *nlmsg;
+ struct sk_buff *skb;
+
+ skb = alloc_skb(sizeof(struct ax25_nlmsg), GFP_ATOMIC);
+ if (!skb)
+ return;
+ nlmsg = (struct ax25_nlmsg *)skb_put(skb, sizeof(struct ax25_nlmsg));
+
+ nlmsg->msg_type = AX25_MSG_RTINFO;
+ strncpy(nlmsg->msg.rtmsg.port_name, dev->name, sizeof(nlmsg->msg.rtmsg.port_name));
+ nlmsg->msg.rtmsg.addr = pkt->addr;
+ netlink_broadcast(axrtnl, skb, 0, ~0, GFP_KERNEL);
+}
+
+void ax25_nlpost_armsg(unsigned int ip_addr, ax25_address *ax_addr, struct net_device *dev)
+{
+ struct ax25_nlmsg *nlmsg;
+ struct sk_buff *skb;
+
+ skb = alloc_skb(sizeof(struct ax25_nlmsg), GFP_ATOMIC);
+ if (!skb)
+ return;
+ nlmsg = (struct ax25_nlmsg *)skb_put(skb, sizeof(struct ax25_nlmsg));
+
+ nlmsg->msg_type = AX25_MSG_ARINFO;
+ strncpy(nlmsg->msg.armsg.port_name, dev->name, sizeof(nlmsg->msg.armsg.port_name));
+ nlmsg->msg.armsg.ip_addr = ip_addr;
+ nlmsg->msg.armsg.ax_addr = *ax_addr;
+
+ netlink_broadcast(axrtnl, skb, 0, ~0, GFP_KERNEL);
+}
+
+void ax25_netlink_init(void)
+{
+ axrtnl = netlink_kernel_create(NETLINK_AX25, ax25_netlink_rcv);
+}
+
+void ax25_netlink_cleanup(void)
+{
+ sock_release(axrtnl->socket);
+}