/* * 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 #include #include #include #include #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); }