Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
drivers
staging
gdm72xx
netlink_k.c
Go to the documentation of this file.
1
/*
2
* Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved.
3
*
4
* This software is licensed under the terms of the GNU General Public
5
* License version 2, as published by the Free Software Foundation, and
6
* may be copied, distributed, and modified under those terms.
7
*
8
* This program is distributed in the hope that it will be useful,
9
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
* GNU General Public License for more details.
12
*/
13
14
#include <linux/module.h>
15
#include <
linux/etherdevice.h
>
16
#include <linux/netlink.h>
17
#include <asm/byteorder.h>
18
#include <
net/sock.h
>
19
20
#if !defined(NLMSG_HDRLEN)
21
#define NLMSG_HDRLEN ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr)))
22
#endif
23
24
#define ND_MAX_GROUP 30
25
#define ND_IFINDEX_LEN sizeof(int)
26
#define ND_NLMSG_SPACE(len) (NLMSG_SPACE(len) + ND_IFINDEX_LEN)
27
#define ND_NLMSG_DATA(nlh) \
28
((void *)((char *)NLMSG_DATA(nlh) + ND_IFINDEX_LEN))
29
#define ND_NLMSG_S_LEN(len) (len+ND_IFINDEX_LEN)
30
#define ND_NLMSG_R_LEN(nlh) (nlh->nlmsg_len-ND_IFINDEX_LEN)
31
#define ND_NLMSG_IFIDX(nlh) NLMSG_DATA(nlh)
32
#define ND_MAX_MSG_LEN 8096
33
34
#if defined(DEFINE_MUTEX)
35
static
DEFINE_MUTEX
(netlink_mutex);
36
#else
37
static
struct
semaphore
netlink_mutex;
38
#define mutex_lock(x) down(x)
39
#define mutex_unlock(x) up(x)
40
#endif
41
42
static
void
(*rcv_cb)(
struct
net_device
*
dev
,
u16
type
,
void
*
msg
,
int
len
);
43
44
static
void
netlink_rcv_cb(
struct
sk_buff
*
skb
)
45
{
46
struct
nlmsghdr
*nlh;
47
struct
net_device
*
dev
;
48
u32
mlen;
49
void
*
msg
;
50
int
ifindex
;
51
52
if
(skb->
len
>=
NLMSG_SPACE
(0)) {
53
nlh = (
struct
nlmsghdr
*)skb->
data
;
54
55
if
(skb->
len
< nlh->
nlmsg_len
||
56
nlh->
nlmsg_len
>
ND_MAX_MSG_LEN
) {
57
printk
(
KERN_ERR
"Invalid length (%d,%d)\n"
, skb->
len
,
58
nlh->
nlmsg_len
);
59
return
;
60
}
61
62
memcpy
(&ifindex,
ND_NLMSG_IFIDX
(nlh),
ND_IFINDEX_LEN
);
63
msg =
ND_NLMSG_DATA
(nlh);
64
mlen =
ND_NLMSG_R_LEN
(nlh);
65
66
if
(rcv_cb) {
67
dev =
dev_get_by_index
(&
init_net
, ifindex);
68
if
(dev) {
69
rcv_cb(dev, nlh->
nlmsg_type
, msg, mlen);
70
dev_put(dev);
71
}
else
72
printk
(
KERN_ERR
"dev_get_by_index(%d) "
73
"is not found.\n"
, ifindex);
74
}
else
75
printk
(
KERN_ERR
"Unregistered Callback\n"
);
76
}
77
}
78
79
static
void
netlink_rcv(
struct
sk_buff
*
skb
)
80
{
81
mutex_lock
(&netlink_mutex);
82
netlink_rcv_cb(skb);
83
mutex_unlock
(&netlink_mutex);
84
}
85
86
struct
sock
*
netlink_init
(
int
unit
,
void
(*
cb
)(
struct
net_device
*dev,
u16
type
,
87
void
*
msg
,
int
len
))
88
{
89
struct
sock
*
sock
;
90
struct
netlink_kernel_cfg
cfg = {
91
.
input
= netlink_rcv,
92
};
93
94
#if !defined(DEFINE_MUTEX)
95
init_MUTEX(&netlink_mutex);
96
#endif
97
98
sock = netlink_kernel_create(&
init_net
, unit, &cfg);
99
100
if
(sock)
101
rcv_cb =
cb
;
102
103
return
sock
;
104
}
105
106
void
netlink_exit
(
struct
sock
*
sock
)
107
{
108
netlink_kernel_release
(sock);
109
}
110
111
int
netlink_send
(
struct
sock
*
sock
,
int
group
,
u16
type
,
void
*
msg
,
int
len)
112
{
113
static
u32
seq
;
114
struct
sk_buff
*
skb
=
NULL
;
115
struct
nlmsghdr
*nlh;
116
int
ret
= 0;
117
118
if
(group >
ND_MAX_GROUP
) {
119
printk
(
KERN_ERR
"Group %d is invalied.\n"
, group);
120
printk
(
KERN_ERR
"Valid group is 0 ~ %d.\n"
,
ND_MAX_GROUP
);
121
return
-
EINVAL
;
122
}
123
124
skb = alloc_skb(
NLMSG_SPACE
(len),
GFP_ATOMIC
);
125
if
(!skb) {
126
printk
(
KERN_ERR
"netlink_broadcast ret=%d\n"
, ret);
127
return
-
ENOMEM
;
128
}
129
130
seq++;
131
nlh = nlmsg_put(skb, 0, seq, type, len, 0);
132
if
(!nlh) {
133
kfree_skb
(skb);
134
return
-
EMSGSIZE
;
135
}
136
memcpy
(nlmsg_data(nlh), msg, len);
137
138
NETLINK_CB
(skb).portid = 0;
139
NETLINK_CB
(skb).dst_group = 0;
140
141
ret =
netlink_broadcast
(sock, skb, 0, group+1,
GFP_ATOMIC
);
142
143
if
(!ret)
144
return
len;
145
else
{
146
if
(ret != -
ESRCH
) {
147
printk
(
KERN_ERR
"netlink_broadcast g=%d, t=%d, l=%d, r=%d\n"
,
148
group, type, len, ret);
149
}
150
ret = 0;
151
}
152
return
ret
;
153
}
Generated on Thu Jan 10 2013 14:28:31 for Linux Kernel by
1.8.2