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
,
20 struct nlattr
*wowlan
, *pattern
;
21 struct nl_msg
*patterns
= NULL
;
25 } parse_state
= PS_REG
;
27 unsigned char *pat
, *mask
;
31 wowlan
= nla_nest_start(msg
, NL80211_ATTR_WOWLAN_TRIGGERS
);
36 switch (parse_state
) {
38 if (strcmp(argv
[0], "any") == 0)
39 NLA_PUT_FLAG(msg
, NL80211_WOWLAN_TRIG_ANY
);
40 else if (strcmp(argv
[0], "disconnect") == 0)
41 NLA_PUT_FLAG(msg
, NL80211_WOWLAN_TRIG_DISCONNECT
);
42 else if (strcmp(argv
[0], "magic-packet") == 0)
43 NLA_PUT_FLAG(msg
, NL80211_WOWLAN_TRIG_MAGIC_PKT
);
44 else if (strcmp(argv
[0], "gtk-rekey-failure") == 0)
45 NLA_PUT_FLAG(msg
, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE
);
46 else if (strcmp(argv
[0], "eap-identity-request") == 0)
47 NLA_PUT_FLAG(msg
, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST
);
48 else if (strcmp(argv
[0], "4way-handshake") == 0)
49 NLA_PUT_FLAG(msg
, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE
);
50 else if (strcmp(argv
[0], "rfkill-release") == 0)
51 NLA_PUT_FLAG(msg
, NL80211_WOWLAN_TRIG_RFKILL_RELEASE
);
52 else if (strcmp(argv
[0], "patterns") == 0) {
54 patterns
= nlmsg_alloc();
65 if (parse_hex_mask(argv
[0], &pat
, &patlen
, &mask
)) {
69 pattern
= nla_nest_start(patterns
, ++patnum
);
70 NLA_PUT(patterns
, NL80211_WOWLAN_PKTPAT_MASK
,
71 DIV_ROUND_UP(patlen
, 8), mask
);
72 NLA_PUT(patterns
, NL80211_WOWLAN_PKTPAT_PATTERN
,
74 nla_nest_end(patterns
, pattern
);
84 nla_put_nested(msg
, NL80211_WOWLAN_TRIG_PKT_PATTERN
,
87 nla_nest_end(msg
, wowlan
);
93 COMMAND(wowlan
, enable
, "[any] [disconnect] [magic-packet] [gtk-rekey-failure] [eap-identity-request]"
94 " [4way-handshake] [rfkill-release] [patterns <pattern>*]",
95 NL80211_CMD_SET_WOWLAN
, 0, CIB_PHY
, handle_wowlan_enable
,
96 "Enable WoWLAN with the given triggers.\n"
97 "Each pattern is given as a bytestring with '-' in places where any byte\n"
98 "may be present, e.g. 00:11:22:-:44 will match 00:11:22:33:44 and\n"
99 "00:11:22:33:ff:44 etc.");
102 static int handle_wowlan_disable(struct nl80211_state
*state
, struct nl_cb
*cb
,
103 struct nl_msg
*msg
, int argc
, char **argv
,
106 /* just a set w/o wowlan attribute */
109 COMMAND(wowlan
, disable
, "", NL80211_CMD_SET_WOWLAN
, 0, CIB_PHY
, handle_wowlan_disable
,
113 static int print_wowlan_handler(struct nl_msg
*msg
, void *arg
)
115 struct nlattr
*attrs
[NL80211_ATTR_MAX
+ 1];
116 struct nlattr
*trig
[NUM_NL80211_WOWLAN_TRIG
];
117 struct genlmsghdr
*gnlh
= nlmsg_data(nlmsg_hdr(msg
));
118 struct nlattr
*pattern
;
121 nla_parse(attrs
, NL80211_ATTR_MAX
, genlmsg_attrdata(gnlh
, 0),
122 genlmsg_attrlen(gnlh
, 0), NULL
);
124 if (!attrs
[NL80211_ATTR_WOWLAN_TRIGGERS
]) {
125 printf("WoWLAN is disabled.\n");
129 /* XXX: use policy */
130 nla_parse(trig
, MAX_NL80211_WOWLAN_TRIG
,
131 nla_data(attrs
[NL80211_ATTR_WOWLAN_TRIGGERS
]),
132 nla_len(attrs
[NL80211_ATTR_WOWLAN_TRIGGERS
]),
135 printf("WoWLAN is enabled:\n");
136 if (trig
[NL80211_WOWLAN_TRIG_ANY
])
137 printf(" * wake up on special any trigger\n");
138 if (trig
[NL80211_WOWLAN_TRIG_DISCONNECT
])
139 printf(" * wake up on disconnect\n");
140 if (trig
[NL80211_WOWLAN_TRIG_MAGIC_PKT
])
141 printf(" * wake up on magic packet\n");
142 if (trig
[NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE
])
143 printf(" * wake up on GTK rekeying failure\n");
144 if (trig
[NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST
])
145 printf(" * wake up on EAP identity request\n");
146 if (trig
[NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE
])
147 printf(" * wake up on 4-way handshake\n");
148 if (trig
[NL80211_WOWLAN_TRIG_RFKILL_RELEASE
])
149 printf(" * wake up on RF-kill release\n");
150 if (trig
[NL80211_WOWLAN_TRIG_PKT_PATTERN
]) {
151 nla_for_each_nested(pattern
,
152 trig
[NL80211_WOWLAN_TRIG_PKT_PATTERN
],
154 struct nlattr
*patattr
[NUM_NL80211_WOWLAN_PKTPAT
];
155 int i
, patlen
, masklen
;
157 nla_parse(patattr
, MAX_NL80211_WOWLAN_PKTPAT
,
158 nla_data(pattern
), nla_len(pattern
),
160 if (!patattr
[NL80211_WOWLAN_PKTPAT_MASK
] ||
161 !patattr
[NL80211_WOWLAN_PKTPAT_PATTERN
]) {
162 printf(" * (invalid pattern specification)\n");
165 masklen
= nla_len(patattr
[NL80211_WOWLAN_PKTPAT_MASK
]);
166 patlen
= nla_len(patattr
[NL80211_WOWLAN_PKTPAT_PATTERN
]);
167 if (DIV_ROUND_UP(patlen
, 8) != masklen
) {
168 printf(" * (invalid pattern specification)\n");
171 printf(" * wake up on pattern: ");
172 pat
= nla_data(patattr
[NL80211_WOWLAN_PKTPAT_PATTERN
]);
173 mask
= nla_data(patattr
[NL80211_WOWLAN_PKTPAT_MASK
]);
174 for (i
= 0; i
< patlen
; i
++) {
175 if (mask
[i
/ 8] & (1 << (i
% 8)))
176 printf("%.2x", pat
[i
]);
189 static int handle_wowlan_show(struct nl80211_state
*state
, struct nl_cb
*cb
,
190 struct nl_msg
*msg
, int argc
, char **argv
,
193 nl_cb_set(cb
, NL_CB_VALID
, NL_CB_CUSTOM
,
194 print_wowlan_handler
, NULL
);
198 COMMAND(wowlan
, show
, "", NL80211_CMD_GET_WOWLAN
, 0, CIB_PHY
, handle_wowlan_show
,
199 "Show WoWLAN status.");