5 #include <netlink/genl/genl.h>
6 #include <netlink/genl/family.h>
7 #include <netlink/genl/ctrl.h>
8 #include <netlink/msg.h>
9 #include <netlink/attr.h>
16 static int handle_wowlan_enable(struct nl80211_state
*state
, struct nl_cb
*cb
,
17 struct nl_msg
*msg
, int argc
, char **argv
)
19 struct nlattr
*wowlan
, *pattern
;
20 struct nl_msg
*patterns
= NULL
;
24 } parse_state
= PS_REG
;
26 unsigned char *pat
, *mask
;
30 wowlan
= nla_nest_start(msg
, NL80211_ATTR_WOWLAN_TRIGGERS
);
35 switch (parse_state
) {
37 if (strcmp(argv
[0], "any") == 0)
38 NLA_PUT_FLAG(msg
, NL80211_WOWLAN_TRIG_ANY
);
39 else if (strcmp(argv
[0], "disconnect") == 0)
40 NLA_PUT_FLAG(msg
, NL80211_WOWLAN_TRIG_DISCONNECT
);
41 else if (strcmp(argv
[0], "magic-packet") == 0)
42 NLA_PUT_FLAG(msg
, NL80211_WOWLAN_TRIG_MAGIC_PKT
);
43 else if (strcmp(argv
[0], "gtk-rekey-failure") == 0)
44 NLA_PUT_FLAG(msg
, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE
);
45 else if (strcmp(argv
[0], "eap-identity-request") == 0)
46 NLA_PUT_FLAG(msg
, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST
);
47 else if (strcmp(argv
[0], "4way-handshake") == 0)
48 NLA_PUT_FLAG(msg
, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE
);
49 else if (strcmp(argv
[0], "rfkill-release") == 0)
50 NLA_PUT_FLAG(msg
, NL80211_WOWLAN_TRIG_RFKILL_RELEASE
);
51 else if (strcmp(argv
[0], "patterns") == 0) {
53 patterns
= nlmsg_alloc();
64 if (parse_hex_mask(argv
[0], &pat
, &patlen
, &mask
)) {
68 pattern
= nla_nest_start(patterns
, ++patnum
);
69 NLA_PUT(patterns
, NL80211_WOWLAN_PKTPAT_MASK
,
70 DIV_ROUND_UP(patlen
, 8), mask
);
71 NLA_PUT(patterns
, NL80211_WOWLAN_PKTPAT_PATTERN
,
73 nla_nest_end(patterns
, pattern
);
83 nla_put_nested(msg
, NL80211_WOWLAN_TRIG_PKT_PATTERN
,
86 nla_nest_end(msg
, wowlan
);
92 COMMAND(wowlan
, enable
, "[any] [disconnect] [magic-packet] [gtk-rekey-failure] [eap-identity-request]"
93 " [4way-handshake] [rfkill-release] [patterns <pattern>*]",
94 NL80211_CMD_SET_WOWLAN
, 0, CIB_PHY
, handle_wowlan_enable
,
95 "Enable WoWLAN with the given triggers.\n"
96 "Each pattern is given as a bytestring with '-' in places where any byte\n"
97 "may be present, e.g. 00:11:22:-:44 will match 00:11:22:33:44 and\n"
98 "00:11:22:33:ff:44 etc.");
101 static int handle_wowlan_disable(struct nl80211_state
*state
, struct nl_cb
*cb
,
102 struct nl_msg
*msg
, int argc
, char **argv
)
104 /* just a set w/o wowlan attribute */
107 COMMAND(wowlan
, disable
, "", NL80211_CMD_SET_WOWLAN
, 0, CIB_PHY
, handle_wowlan_disable
,
111 static int print_wowlan_handler(struct nl_msg
*msg
, void *arg
)
113 struct nlattr
*attrs
[NL80211_ATTR_MAX
+ 1];
114 struct nlattr
*trig
[NUM_NL80211_WOWLAN_TRIG
];
115 struct genlmsghdr
*gnlh
= nlmsg_data(nlmsg_hdr(msg
));
116 struct nlattr
*pattern
;
119 nla_parse(attrs
, NL80211_ATTR_MAX
, genlmsg_attrdata(gnlh
, 0),
120 genlmsg_attrlen(gnlh
, 0), NULL
);
122 if (!attrs
[NL80211_ATTR_WOWLAN_TRIGGERS
]) {
123 printf("WoWLAN is disabled.\n");
127 /* XXX: use policy */
128 nla_parse(trig
, MAX_NL80211_WOWLAN_TRIG
,
129 nla_data(attrs
[NL80211_ATTR_WOWLAN_TRIGGERS
]),
130 nla_len(attrs
[NL80211_ATTR_WOWLAN_TRIGGERS
]),
133 printf("WoWLAN is enabled:\n");
134 if (trig
[NL80211_WOWLAN_TRIG_ANY
])
135 printf(" * wake up on special any trigger\n");
136 if (trig
[NL80211_WOWLAN_TRIG_DISCONNECT
])
137 printf(" * wake up on disconnect\n");
138 if (trig
[NL80211_WOWLAN_TRIG_MAGIC_PKT
])
139 printf(" * wake up on magic packet\n");
140 if (trig
[NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE
])
141 printf(" * wake up on GTK rekeying failure\n");
142 if (trig
[NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST
])
143 printf(" * wake up on EAP identity request\n");
144 if (trig
[NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE
])
145 printf(" * wake up on 4-way handshake\n");
146 if (trig
[NL80211_WOWLAN_TRIG_RFKILL_RELEASE
])
147 printf(" * wake up on RF-kill release\n");
148 if (trig
[NL80211_WOWLAN_TRIG_PKT_PATTERN
]) {
149 nla_for_each_nested(pattern
,
150 trig
[NL80211_WOWLAN_TRIG_PKT_PATTERN
],
152 struct nlattr
*patattr
[NUM_NL80211_WOWLAN_PKTPAT
];
153 int i
, patlen
, masklen
;
155 nla_parse(patattr
, MAX_NL80211_WOWLAN_PKTPAT
,
156 nla_data(pattern
), nla_len(pattern
),
158 if (!patattr
[NL80211_WOWLAN_PKTPAT_MASK
] ||
159 !patattr
[NL80211_WOWLAN_PKTPAT_PATTERN
]) {
160 printf(" * (invalid pattern specification)\n");
163 masklen
= nla_len(patattr
[NL80211_WOWLAN_PKTPAT_MASK
]);
164 patlen
= nla_len(patattr
[NL80211_WOWLAN_PKTPAT_PATTERN
]);
165 if (DIV_ROUND_UP(patlen
, 8) != masklen
) {
166 printf(" * (invalid pattern specification)\n");
169 printf(" * wake up on pattern: ");
170 pat
= nla_data(patattr
[NL80211_WOWLAN_PKTPAT_PATTERN
]);
171 mask
= nla_data(patattr
[NL80211_WOWLAN_PKTPAT_MASK
]);
172 for (i
= 0; i
< patlen
; i
++) {
173 if (mask
[i
/ 8] & (1 << (i
% 8)))
174 printf("%.2x", pat
[i
]);
187 static int handle_wowlan_show(struct nl80211_state
*state
, struct nl_cb
*cb
,
188 struct nl_msg
*msg
, int argc
, char **argv
)
190 nl_cb_set(cb
, NL_CB_VALID
, NL_CB_CUSTOM
,
191 print_wowlan_handler
, NULL
);
195 COMMAND(wowlan
, show
, "", NL80211_CMD_GET_WOWLAN
, 0, CIB_PHY
, handle_wowlan_show
,
196 "Show WoWLAN status.");