1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
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);
}
|