nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /* |
2 | * nl80211 linux driver interface. |
||
3 | * |
||
4 | * Copyright (C) 1999-2013, Broadcom Corporation |
||
5 | * |
||
6 | * Permission to use, copy, modify, and/or distribute this software for any |
||
7 | * purpose with or without fee is hereby granted, provided that the above |
||
8 | * copyright notice and this permission notice appear in all copies. |
||
9 | * |
||
10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
||
11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
||
12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
||
13 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
||
14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
||
15 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
||
16 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
||
17 | * |
||
18 | * $Id: $ |
||
19 | */ |
||
20 | #include <errno.h> |
||
21 | #include <linux/nl80211.h> |
||
22 | #include <dhdioctl.h> |
||
23 | #include "dhdu_nl80211.h" |
||
24 | |||
25 | /* libnl 1.x compatibility code */ |
||
26 | #if !defined(CONFIG_LIBNL20) && !defined(CONFIG_LIBNL30) |
||
27 | static inline struct nl_handle *nl_socket_alloc(void) |
||
28 | { |
||
29 | return nl_handle_alloc(); |
||
30 | } |
||
31 | |||
32 | static inline void nl_socket_free(struct nl_sock *h) |
||
33 | { |
||
34 | nl_handle_destroy(h); |
||
35 | } |
||
36 | #endif /* CONFIG_LIBNL20 && CONFIG_LIBNL30 */ |
||
37 | |||
38 | static int dhd_nl_error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg) |
||
39 | { |
||
40 | int *ret = arg; |
||
41 | *ret = err->error; |
||
42 | return NL_STOP; |
||
43 | } |
||
44 | |||
45 | static int dhd_nl_finish_handler(struct nl_msg *msg, void *arg) |
||
46 | { |
||
47 | int *ret = arg; |
||
48 | *ret = 0; |
||
49 | return NL_SKIP; |
||
50 | } |
||
51 | |||
52 | static int dhd_nl_ack_handler(struct nl_msg *msg, void *arg) |
||
53 | { |
||
54 | int *ret = arg; |
||
55 | *ret = 0; |
||
56 | return NL_STOP; |
||
57 | } |
||
58 | |||
59 | static int dhd_nl_valid_handler(struct nl_msg *msg, void *arg) |
||
60 | { |
||
61 | return NL_SKIP; |
||
62 | } |
||
63 | |||
64 | int dhd_nl_sock_connect(struct dhd_netlink_info *dhd_nli) |
||
65 | { |
||
66 | dhd_nli->nl = nl_socket_alloc(); |
||
67 | if (dhd_nli->nl == NULL) |
||
68 | return -1; |
||
69 | |||
70 | if (genl_connect(dhd_nli->nl) < 0) { |
||
71 | fprintf(stderr, "netlink connection failed\n"); |
||
72 | goto err; |
||
73 | } |
||
74 | |||
75 | dhd_nli->nl_id = genl_ctrl_resolve(dhd_nli->nl, "nl80211"); |
||
76 | if (dhd_nli->nl_id < 0) { |
||
77 | fprintf(stderr, "'nl80211' netlink not found\n"); |
||
78 | goto err; |
||
79 | } |
||
80 | |||
81 | dhd_nli->cb = nl_cb_alloc(NL_CB_DEBUG); |
||
82 | if (dhd_nli->cb == NULL) |
||
83 | goto err; |
||
84 | |||
85 | nl_socket_set_cb(dhd_nli->nl, dhd_nli->cb); |
||
86 | return 0; |
||
87 | |||
88 | err: |
||
89 | nl_cb_put(dhd_nli->cb); |
||
90 | nl_socket_free(dhd_nli->nl); |
||
91 | fprintf(stderr, "nl80211 connection failed\n"); |
||
92 | return -1; |
||
93 | } |
||
94 | |||
95 | void dhd_nl_sock_disconnect(struct dhd_netlink_info *dhd_nli) |
||
96 | { |
||
97 | nl_cb_put(dhd_nli->cb); |
||
98 | nl_socket_free(dhd_nli->nl); |
||
99 | } |
||
100 | |||
101 | int dhd_nl_do_testmode(struct dhd_netlink_info *dhd_nli, dhd_ioctl_t *ioc) |
||
102 | { |
||
103 | struct nl_msg *msg; |
||
104 | int err; |
||
105 | |||
106 | msg = nlmsg_alloc(); |
||
107 | if (msg == NULL) |
||
108 | return -ENOMEM; |
||
109 | |||
110 | /* fill testmode message */ |
||
111 | genlmsg_put(msg, 0, 0, dhd_nli->nl_id, 0, 0, |
||
112 | NL80211_CMD_TESTMODE, 0); |
||
113 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dhd_nli->ifidx); |
||
114 | NLA_PUT(msg, NL80211_ATTR_TESTDATA, sizeof(*ioc), ioc); |
||
115 | |||
116 | err = nl_send_auto_complete(dhd_nli->nl, msg); |
||
117 | if (err < 0) |
||
118 | goto out; |
||
119 | |||
120 | err = 1; |
||
121 | nl_cb_err(dhd_nli->cb, NL_CB_CUSTOM, dhd_nl_error_handler, &err); |
||
122 | nl_cb_set(dhd_nli->cb, NL_CB_ACK, NL_CB_CUSTOM, |
||
123 | dhd_nl_ack_handler, &err); |
||
124 | nl_cb_set(dhd_nli->cb, NL_CB_FINISH, NL_CB_CUSTOM, |
||
125 | dhd_nl_finish_handler, &err); |
||
126 | nl_cb_set(dhd_nli->cb, NL_CB_VALID, NL_CB_CUSTOM, |
||
127 | dhd_nl_valid_handler, &err); |
||
128 | while (err > 0) |
||
129 | nl_recvmsgs(dhd_nli->nl, dhd_nli->cb); |
||
130 | out: |
||
131 | nlmsg_free(msg); |
||
132 | return err; |
||
133 | |||
134 | nla_put_failure: |
||
135 | fprintf(stderr, "setting netlink attribute failed\n"); |
||
136 | err = -EFAULT; |
||
137 | goto out; |
||
138 | } |