2 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
7 * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
8 * Sun elects to license this software under the BSD license.
9 * See README for more details.
25 #include <libdllink.h>
26 #include <sys/ethernet.h>
32 #include "l2_packet.h"
34 extern struct wpa_driver_ops wpa_driver_wifi_ops
;
35 int wpa_debug_level
= MSG_ERROR
;
38 * wpa_printf - conditional printf
39 * @level: priority level (MSG_*) of the message
40 * @fmt: printf format string, followed by optional arguments
42 * This function is used to print conditional debugging and error messages. The
43 * output may be directed to stdout, stderr, and/or syslog based on
47 wpa_printf(int level
, char *fmt
, ...)
50 char buffer
[MAX_LOGBUF
];
52 if (level
< wpa_debug_level
)
57 /* LINTED E_SEC_PRINTF_VAR_FMT */
58 (void) vsnprintf(buffer
, sizeof (buffer
), fmt
, ap
);
62 syslog(LOG_NOTICE
| LOG_DAEMON
, "%s", buffer
);
66 * wpa_hexdump - conditional hex dump
67 * @level: priority level (MSG_*) of the message
68 * @title: title of for the message
69 * @buf: data buffer to be dumped
70 * @len: length of the @buf
72 * This function is used to print conditional debugging and error messages. The
73 * output may be directed to stdout, stderr, and/or syslog based on
74 * configuration. The contents of @buf is printed out has hex dump.
77 wpa_hexdump(int level
, const char *title
, const uint8_t *buf
, size_t len
)
80 char buffer
[MAX_LOGBUF
], tmp
[4];
83 if (level
< wpa_debug_level
)
86 (void) snprintf(buffer
, sizeof (buffer
), "%s - hexdump(len=%d):",
90 for (i
= 0; i
< len
; i
++) {
91 (void) sprintf(tmp
, " %02x", buf
[i
]);
94 if (n
>= MAX_LOGBUF
) break;
96 (void) strlcat(buffer
, tmp
, sizeof (buffer
));
99 syslog(LOG_NOTICE
| LOG_DAEMON
, "%s", buffer
);
103 wpa_ssid_txt(char *ssid
, size_t ssid_len
)
105 static char ssid_txt
[MAX_ESSID_LENGTH
+ 1];
108 if (ssid_len
> MAX_ESSID_LENGTH
)
109 ssid_len
= MAX_ESSID_LENGTH
;
110 (void) memcpy(ssid_txt
, ssid
, ssid_len
);
111 ssid_txt
[ssid_len
] = '\0';
112 for (pos
= ssid_txt
; *pos
!= '\0'; pos
++) {
113 if ((uint8_t)*pos
< 32 || (uint8_t)*pos
>= 127)
121 wpa_supplicant_scan(void *eloop_ctx
, void *timeout_ctx
)
123 struct wpa_supplicant
*wpa_s
= eloop_ctx
;
124 struct wpa_ssid
*ssid
;
126 if (wpa_s
->conf
== NULL
)
129 if (wpa_s
->wpa_state
== WPA_DISCONNECTED
)
130 wpa_s
->wpa_state
= WPA_SCANNING
;
132 ssid
= wpa_s
->conf
->ssid
;
133 wpa_printf(MSG_DEBUG
, "Starting AP scan (%s SSID)",
134 ssid
? "specific": "broadcast");
137 wpa_printf(MSG_DEBUG
, "Scan SSID: %s", ssid
->ssid
);
140 if (wpa_s
->driver
->scan(wpa_s
->handle
, wpa_s
->linkid
)) {
141 wpa_printf(MSG_WARNING
, "Failed to initiate AP scan.");
146 wpa_supplicant_req_scan(struct wpa_supplicant
*wpa_s
, int sec
, int usec
)
148 wpa_printf(MSG_DEBUG
, "Setting scan request: %d sec %d usec",
150 (void) eloop_cancel_timeout(wpa_supplicant_scan
, wpa_s
, NULL
);
151 (void) eloop_register_timeout(sec
, usec
, wpa_supplicant_scan
,
156 wpa_supplicant_cancel_scan(struct wpa_supplicant
*wpa_s
)
158 wpa_printf(MSG_DEBUG
, "Cancelling scan request");
159 eloop_cancel_timeout(wpa_supplicant_scan
, wpa_s
, NULL
);
164 wpa_supplicant_timeout(void *eloop_ctx
, void *timeout_ctx
)
166 struct wpa_supplicant
*wpa_s
= eloop_ctx
;
168 wpa_printf(MSG_INFO
, "Authentication with " MACSTR
" timed out.",
169 MAC2STR(wpa_s
->bssid
));
171 wpa_s
->reassociate
= 1;
172 wpa_supplicant_req_scan(wpa_s
, 0, 0);
176 wpa_supplicant_req_auth_timeout(struct wpa_supplicant
*wpa_s
,
179 wpa_printf(MSG_DEBUG
, "Setting authentication timeout: %d sec "
180 "%d usec", sec
, usec
);
181 eloop_cancel_timeout(wpa_supplicant_timeout
, wpa_s
, NULL
);
182 (void) eloop_register_timeout(sec
, usec
, wpa_supplicant_timeout
,
187 wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant
*wpa_s
)
189 wpa_printf(MSG_DEBUG
, "Cancelling authentication timeout");
190 eloop_cancel_timeout(wpa_supplicant_timeout
, wpa_s
, NULL
);
194 wpa_supplicant_cleanup(struct wpa_supplicant
*wpa_s
)
196 l2_packet_deinit(wpa_s
->l2
);
199 if (wpa_s
->conf
!= NULL
) {
200 wpa_config_free(wpa_s
->conf
);
204 dladm_close(wpa_s
->handle
);
205 free(wpa_s
->ap_wpa_ie
);
206 pmksa_candidate_free(wpa_s
);
207 pmksa_cache_free(wpa_s
);
211 wpa_clear_keys(struct wpa_supplicant
*wpa_s
, uint8_t *addr
)
213 wpa_s
->driver
->set_key(wpa_s
->handle
, wpa_s
->linkid
, WPA_ALG_NONE
,
214 (uint8_t *)"\xff\xff\xff\xff\xff\xff", 0, 0, NULL
, 0, NULL
, 0);
215 wpa_s
->driver
->set_key(wpa_s
->handle
, wpa_s
->linkid
, WPA_ALG_NONE
,
216 (uint8_t *)"\xff\xff\xff\xff\xff\xff", 1, 0, NULL
, 0, NULL
, 0);
217 wpa_s
->driver
->set_key(wpa_s
->handle
, wpa_s
->linkid
, WPA_ALG_NONE
,
218 (uint8_t *)"\xff\xff\xff\xff\xff\xff", 2, 0, NULL
, 0, NULL
, 0);
219 wpa_s
->driver
->set_key(wpa_s
->handle
, wpa_s
->linkid
, WPA_ALG_NONE
,
220 (uint8_t *)"\xff\xff\xff\xff\xff\xff", 3, 0, NULL
, 0, NULL
, 0);
222 wpa_s
->driver
->set_key(wpa_s
->handle
, wpa_s
->linkid
,
223 WPA_ALG_NONE
, addr
, 0, 0, NULL
, 0, NULL
, 0);
228 wpa_supplicant_mark_disassoc(struct wpa_supplicant
*wpa_s
)
230 wpa_s
->wpa_state
= WPA_DISCONNECTED
;
231 (void) memset(wpa_s
->bssid
, 0, IEEE80211_ADDR_LEN
);
235 wpa_supplicant_set_suites(struct wpa_supplicant
*wpa_s
,
236 dladm_wlan_ess_t
*bss
, struct wpa_ssid
*ssid
,
237 uint8_t *wpa_ie
, int *wpa_ie_len
)
239 struct wpa_ie_data ie
;
245 if (bss
->we_wpa_ie_len
&& bss
->we_wpa_ie
[0] == RSN_INFO_ELEM
&&
246 (ssid
->proto
& WPA_PROTO_RSN
)) {
247 wpa_printf(MSG_DEBUG
, "RSN: using IEEE 802.11i/D9.0");
248 proto
= WPA_PROTO_RSN
;
250 wpa_printf(MSG_DEBUG
, "WPA: using IEEE 802.11i/D3.0");
251 proto
= WPA_PROTO_WPA
;
254 ap_ie
= bss
->we_wpa_ie
;
255 ap_ie_len
= bss
->we_wpa_ie_len
;
257 if (wpa_parse_wpa_ie(wpa_s
, ap_ie
, ap_ie_len
, &ie
)) {
258 wpa_printf(MSG_WARNING
, "WPA: Failed to parse WPA IE for "
259 "the selected BSS.");
263 wpa_s
->proto
= proto
;
264 free(wpa_s
->ap_wpa_ie
);
265 wpa_s
->ap_wpa_ie
= malloc(ap_ie_len
);
266 (void) memcpy(wpa_s
->ap_wpa_ie
, ap_ie
, ap_ie_len
);
267 wpa_s
->ap_wpa_ie_len
= ap_ie_len
;
269 sel
= ie
.group_cipher
& ssid
->group_cipher
;
270 if (sel
& WPA_CIPHER_CCMP
) {
271 wpa_s
->group_cipher
= WPA_CIPHER_CCMP
;
272 } else if (sel
& WPA_CIPHER_TKIP
) {
273 wpa_s
->group_cipher
= WPA_CIPHER_TKIP
;
274 } else if (sel
& WPA_CIPHER_WEP104
) {
275 wpa_s
->group_cipher
= WPA_CIPHER_WEP104
;
276 } else if (sel
& WPA_CIPHER_WEP40
) {
277 wpa_s
->group_cipher
= WPA_CIPHER_WEP40
;
279 wpa_printf(MSG_WARNING
, "WPA: Failed to select group cipher.");
283 sel
= ie
.pairwise_cipher
& ssid
->pairwise_cipher
;
284 if (sel
& WPA_CIPHER_CCMP
) {
285 wpa_s
->pairwise_cipher
= WPA_CIPHER_CCMP
;
286 } else if (sel
& WPA_CIPHER_TKIP
) {
287 wpa_s
->pairwise_cipher
= WPA_CIPHER_TKIP
;
288 } else if (sel
& WPA_CIPHER_NONE
) {
289 wpa_s
->pairwise_cipher
= WPA_CIPHER_NONE
;
291 wpa_printf(MSG_WARNING
, "WPA: Failed to select pairwise "
296 sel
= ie
.key_mgmt
& ssid
->key_mgmt
;
297 if (sel
& WPA_KEY_MGMT_IEEE8021X
) {
298 wpa_s
->key_mgmt
= WPA_KEY_MGMT_IEEE8021X
;
299 } else if (sel
& WPA_KEY_MGMT_PSK
) {
300 wpa_s
->key_mgmt
= WPA_KEY_MGMT_PSK
;
302 wpa_printf(MSG_WARNING
, "WPA: Failed to select authenticated "
303 "key management type.");
307 *wpa_ie_len
= wpa_gen_wpa_ie(wpa_s
, wpa_ie
);
308 if (*wpa_ie_len
< 0) {
309 wpa_printf(MSG_WARNING
, "WPA: Failed to generate WPA IE.");
312 wpa_hexdump(MSG_DEBUG
, "WPA: Own WPA IE", wpa_ie
, *wpa_ie_len
);
314 if (ssid
->key_mgmt
& WPA_KEY_MGMT_PSK
)
315 (void) memcpy(wpa_s
->pmk
, ssid
->psk
, PMK_LEN
);
316 else if (wpa_s
->cur_pmksa
)
317 (void) memcpy(wpa_s
->pmk
, wpa_s
->cur_pmksa
->pmk
, PMK_LEN
);
319 (void) memset(wpa_s
->pmk
, 0, PMK_LEN
);
325 static void wpa_supplicant_associate(struct wpa_supplicant
*wpa_s
,
326 dladm_wlan_ess_t
*bss
, struct wpa_ssid
*ssid
)
328 uint8_t wpa_ie
[IEEE80211_MAX_OPT_IE
];
331 wpa_s
->reassociate
= 0;
332 wpa_printf(MSG_DEBUG
, "Trying to associate with " MACSTR
333 " (SSID='%s' freq=%d MHz)", MAC2STR(bss
->we_bssid
.wb_bytes
),
334 wpa_ssid_txt((char *)ssid
->ssid
, ssid
->ssid_len
), bss
->we_freq
);
335 wpa_supplicant_cancel_scan(wpa_s
);
337 if (bss
->we_wpa_ie_len
&&
338 (ssid
->key_mgmt
& (WPA_KEY_MGMT_IEEE8021X
| WPA_KEY_MGMT_PSK
))) {
339 wpa_s
->cur_pmksa
= pmksa_cache_get(wpa_s
,
340 bss
->we_bssid
.wb_bytes
, NULL
);
341 if (wpa_s
->cur_pmksa
) {
342 wpa_hexdump(MSG_DEBUG
, "RSN: PMKID",
343 wpa_s
->cur_pmksa
->pmkid
, PMKID_LEN
);
345 if (wpa_supplicant_set_suites(wpa_s
, bss
, ssid
,
346 wpa_ie
, &wpa_ie_len
)) {
347 wpa_printf(MSG_WARNING
, "WPA: Failed to set WPA key "
348 "management and encryption suites");
355 wpa_clear_keys(wpa_s
, bss
->we_bssid
.wb_bytes
);
356 wpa_s
->wpa_state
= WPA_ASSOCIATING
;
357 wpa_s
->driver
->associate(wpa_s
->handle
, wpa_s
->linkid
,
358 (const char *)bss
->we_bssid
.wb_bytes
, wpa_ie
, wpa_ie_len
);
360 /* Timeout for IEEE 802.11 authentication and association */
361 wpa_supplicant_req_auth_timeout(wpa_s
, 15, 0);
365 wpa_supplicant_disassociate(struct wpa_supplicant
*wpa_s
, int reason_code
)
367 uint8_t *addr
= NULL
;
368 wpa_s
->wpa_state
= WPA_DISCONNECTED
;
369 if (memcmp(wpa_s
->bssid
, "\x00\x00\x00\x00\x00\x00",
370 IEEE80211_ADDR_LEN
) != 0) {
371 wpa_s
->driver
->disassociate(wpa_s
->handle
, wpa_s
->linkid
,
375 wpa_clear_keys(wpa_s
, addr
);
378 static dladm_wlan_ess_t
*
379 wpa_supplicant_select_bss(struct wpa_supplicant
*wpa_s
, struct wpa_ssid
*group
,
380 dladm_wlan_ess_t
*results
, int num
, struct wpa_ssid
**selected_ssid
)
382 struct wpa_ssid
*ssid
;
383 dladm_wlan_ess_t
*bss
, *selected
= NULL
;
386 struct wpa_ie_data ie
;
388 wpa_printf(MSG_DEBUG
, "Selecting BSS from scan results (%d)", num
);
393 /* try to find matched AP */
394 for (i
= 0; i
< num
&& !selected
; i
++) {
396 wpa_printf(MSG_DEBUG
, "%d: " MACSTR
" ssid='%s' "
398 i
, MAC2STR(bss
->we_bssid
.wb_bytes
),
399 wpa_ssid_txt(bss
->we_ssid
.we_bytes
, bss
->we_ssid_len
),
401 if (bss
->we_wpa_ie_len
== 0) {
402 wpa_printf(MSG_DEBUG
, " skip - no WPA/RSN IE");
406 if (bss
->we_ssid_len
!= ssid
->ssid_len
||
407 memcmp(bss
->we_ssid
.we_bytes
, ssid
->ssid
,
408 bss
->we_ssid_len
) != 0) {
409 wpa_printf(MSG_DEBUG
, " skip - SSID mismatch");
412 if (!((ssid
->proto
& (WPA_PROTO_RSN
| WPA_PROTO_WPA
)) &&
413 wpa_parse_wpa_ie(wpa_s
, bss
->we_wpa_ie
,
414 bss
->we_wpa_ie_len
, &ie
) == 0)) {
415 wpa_printf(MSG_DEBUG
, " skip - "
416 "could not parse WPA/RSN IE");
419 if (!(ie
.proto
& ssid
->proto
)) {
420 wpa_printf(MSG_DEBUG
, " skip - proto mismatch");
423 if (!(ie
.pairwise_cipher
& ssid
->pairwise_cipher
)) {
424 wpa_printf(MSG_DEBUG
, " skip - PTK cipher mismatch");
427 if (!(ie
.group_cipher
& ssid
->group_cipher
)) {
428 wpa_printf(MSG_DEBUG
, " skip - GTK cipher mismatch");
431 if (!(ie
.key_mgmt
& ssid
->key_mgmt
)) {
432 wpa_printf(MSG_DEBUG
, " skip - key mgmt mismatch");
437 *selected_ssid
= ssid
;
438 wpa_printf(MSG_DEBUG
, " selected");
446 wpa_supplicant_scan_results(struct wpa_supplicant
*wpa_s
)
448 dladm_wlan_ess_t results
[MAX_SCANRESULTS
];
450 dladm_wlan_ess_t
*selected
= NULL
;
451 struct wpa_ssid
*ssid
;
453 (void) memset(results
, 0, sizeof (dladm_wlan_ess_t
) * MAX_SCANRESULTS
);
454 num
= wpa_s
->driver
->get_scan_results(wpa_s
->handle
, wpa_s
->linkid
,
455 results
, MAX_SCANRESULTS
);
456 wpa_printf(MSG_DEBUG
, "Scan results: %d", num
);
459 if (num
> MAX_SCANRESULTS
) {
460 wpa_printf(MSG_INFO
, "Not enough room for all APs (%d < %d)",
461 num
, MAX_SCANRESULTS
);
462 num
= MAX_SCANRESULTS
;
465 selected
= wpa_supplicant_select_bss(wpa_s
,
466 wpa_s
->conf
->ssid
, results
, num
, &ssid
);
469 if (wpa_s
->reassociate
||
470 memcmp(selected
->we_bssid
.wb_bytes
, wpa_s
->bssid
,
471 IEEE80211_ADDR_LEN
) != 0) {
472 wpa_supplicant_associate(wpa_s
, selected
, ssid
);
474 wpa_printf(MSG_DEBUG
, "Already associated with the "
478 wpa_printf(MSG_DEBUG
, "No suitable AP found.");
479 wpa_supplicant_req_scan(wpa_s
, 5, 0); /* wait 5 seconds */
484 * wpa_event_handler - report a driver event for wpa_supplicant
485 * @wpa_s: pointer to wpa_supplicant data; this is the @ctx variable registered
486 * with wpa_driver_events_init()
487 * @event: event type (defined above)
489 * Driver wrapper code should call this function whenever an event is received
493 wpa_event_handler(void *cookie
, wpa_event_type event
)
495 struct wpa_supplicant
*wpa_s
= cookie
;
499 wpa_printf(MSG_DEBUG
, "\nAssociation event\n");
501 if (wpa_s
->wpa_state
< WPA_ASSOCIATED
) {
502 wpa_s
->wpa_state
= WPA_ASSOCIATED
;
503 if (wpa_s
->key_mgmt
== WPA_KEY_MGMT_NONE
) {
504 wpa_supplicant_cancel_auth_timeout(wpa_s
);
506 /* Timeout for receiving first EAPOL packet */
507 wpa_supplicant_req_auth_timeout(wpa_s
, 10, 0);
512 if (wpa_s
->wpa_state
>= WPA_ASSOCIATED
)
513 wpa_supplicant_req_scan(wpa_s
, 0, 100000);
514 wpa_supplicant_mark_disassoc(wpa_s
);
515 wpa_printf(MSG_DEBUG
, "Disconnect event - remove keys");
516 if (wpa_s
->key_mgmt
!= WPA_KEY_MGMT_NONE
)
517 wpa_clear_keys(wpa_s
, wpa_s
->bssid
);
519 case EVENT_SCAN_RESULTS
:
520 wpa_supplicant_scan_results(wpa_s
);
522 (void) memset(wpa_s
->rx_replay_counter
, 0,
523 WPA_REPLAY_COUNTER_LEN
);
524 wpa_s
->rx_replay_counter_set
= 0;
525 wpa_s
->renew_snonce
= 1;
526 wpa_s
->eapol_received
= 0;
529 wpa_printf(MSG_INFO
, "Unknown event %d", event
);
536 wpa_supplicant_terminate(int sig
, void *eloop_ctx
, void *signal_ctx
)
538 wpa_printf(MSG_INFO
, "Signal %d received - terminating", sig
);
543 wpa_supplicant_driver_init(const char *link
, struct wpa_supplicant
*wpa_s
)
545 wpa_s
->l2
= l2_packet_init(link
, ETHERTYPE_EAPOL
,
546 wpa_supplicant_rx_eapol
, wpa_s
);
547 if (wpa_s
->l2
== NULL
)
550 if (l2_packet_get_own_addr(wpa_s
->l2
, wpa_s
->own_addr
)) {
551 (void) fprintf(stderr
, "Failed to get own L2 address\n");
555 if (wpa_s
->driver
->set_wpa(wpa_s
->handle
, wpa_s
->linkid
, 1) < 0) {
556 wpa_printf(MSG_ERROR
, "Failed to enable WPA in the driver.");
560 wpa_clear_keys(wpa_s
, NULL
);
561 wpa_supplicant_req_scan(wpa_s
, 0, 100000);
566 static int door_id
= -1;
570 event_handler(void *cookie
, char *argp
, size_t asize
,
571 door_desc_t
*dp
, uint_t n_desc
)
573 wpa_event_type event
;
575 /* LINTED E_BAD_PTR_CAST_ALIGN */
576 event
= ((wl_events_t
*)argp
)->event
;
577 wpa_event_handler(cookie
, event
);
579 (void) door_return(NULL
, 0, NULL
, 0);
583 * Create the driver to wpad door
586 wpa_supplicant_door_setup(void *cookie
, char *doorname
)
591 wpa_printf(MSG_DEBUG
, "wpa_supplicant_door_setup(%s)", doorname
);
595 door_id
= door_create(event_handler
, cookie
,
596 DOOR_UNREF
| DOOR_REFUSE_DESC
| DOOR_NO_CANCEL
);
603 if (stat(doorname
, &stbuf
) < 0) {
605 if ((newfd
= creat(doorname
, 0666)) < 0) {
606 (void) door_revoke(door_id
);
615 if (fattach(door_id
, doorname
) < 0) {
616 if ((errno
!= EBUSY
) || (fdetach(doorname
) < 0) ||
617 (fattach(door_id
, doorname
) < 0)) {
618 (void) door_revoke(door_id
);
631 wpa_supplicant_door_destroy(char *doorname
)
633 wpa_printf(MSG_DEBUG
, "wpa_supplicant_door_destroy(%s)\n", doorname
);
638 if (door_revoke(door_id
) == -1) {
639 wpa_printf(MSG_ERROR
, "failed to door_revoke(%d) %s, exiting.",
640 door_id
, strerror(errno
));
643 if (fdetach(doorname
) == -1) {
644 wpa_printf(MSG_ERROR
, "failed to fdetach %s: %s, exiting.",
645 doorname
, strerror(errno
));
648 (void) close(door_id
);
652 wpa_config_parse_ssid(struct wpa_ssid
*ssid
, int line
, const char *value
)
656 ssid
->ssid
= (uint8_t *)strdup(value
);
657 ssid
->ssid_len
= strlen(value
);
659 if (ssid
->ssid
== NULL
) {
660 wpa_printf(MSG_ERROR
, "Invalid SSID '%s'.", line
, value
);
663 if (ssid
->ssid_len
> MAX_ESSID_LENGTH
) {
665 wpa_printf(MSG_ERROR
, "Too long SSID '%s'.", line
, value
);
668 wpa_printf(MSG_MSGDUMP
, "SSID: %s", ssid
->ssid
);
672 static struct wpa_ssid
*
673 wpa_config_read_network(struct wpa_supplicant
*wpa_s
)
675 struct wpa_ssid
*ssid
;
676 char buf
[MAX_ESSID_LENGTH
+ 1];
677 dladm_secobj_class_t cl
;
678 uint8_t psk
[MAX_PSK_LENGTH
+ 1];
681 wpa_printf(MSG_MSGDUMP
, "Start of a new network configration");
683 ssid
= (struct wpa_ssid
*)malloc(sizeof (*ssid
));
686 (void) memset(ssid
, 0, sizeof (*ssid
));
689 * Set default supported values
691 ssid
->proto
= WPA_PROTO_WPA
| WPA_PROTO_RSN
;
692 ssid
->pairwise_cipher
= WPA_CIPHER_CCMP
| WPA_CIPHER_TKIP
;
693 ssid
->group_cipher
= WPA_CIPHER_CCMP
| WPA_CIPHER_TKIP
|
694 WPA_CIPHER_WEP104
| WPA_CIPHER_WEP40
;
695 ssid
->key_mgmt
= WPA_KEY_MGMT_PSK
; /* | WPA_KEY_MGMT_IEEE8021X; */
697 (void) memset(buf
, 0, MAX_ESSID_LENGTH
+ 1);
698 wpa_s
->driver
->get_ssid(wpa_s
->handle
, wpa_s
->linkid
, (char *)buf
);
700 (void) wpa_config_parse_ssid(ssid
, 0, buf
);
702 key_len
= sizeof (psk
);
703 (void) dladm_get_secobj(wpa_s
->handle
, (const char *)wpa_s
->kname
, &cl
,
704 psk
, &key_len
, DLADM_OPT_ACTIVE
);
706 ssid
->passphrase
= strdup((const char *)psk
);
708 if (ssid
->passphrase
) {
709 pbkdf2_sha1(ssid
->passphrase
, (char *)ssid
->ssid
,
710 ssid
->ssid_len
, 4096, ssid
->psk
, PMK_LEN
);
711 wpa_hexdump(MSG_MSGDUMP
, "PSK (from passphrase)",
716 if ((ssid
->key_mgmt
& WPA_KEY_MGMT_PSK
) && !ssid
->psk_set
) {
717 wpa_printf(MSG_ERROR
, "WPA-PSK accepted for key "
718 "management, but no PSK configured.");
727 wpa_config_read(void *arg
)
729 struct wpa_ssid
*ssid
;
730 struct wpa_config
*config
;
731 struct wpa_supplicant
*wpa_s
= arg
;
733 config
= malloc(sizeof (*config
));
736 (void) memset(config
, 0, sizeof (*config
));
737 config
->eapol_version
= 1; /* fixed value */
739 wpa_printf(MSG_DEBUG
, "Reading configuration parameters from driver\n");
741 ssid
= wpa_config_read_network(wpa_s
);
743 wpa_config_free(config
);
753 wpa_config_free(struct wpa_config
*config
)
755 struct wpa_ssid
*ssid
= config
->ssid
;
759 free(ssid
->passphrase
);
766 * make sure wpad is running under SMF context.
773 return (((fmri
= getenv("SMF_FMRI")) != NULL
) &&
774 (strstr(fmri
, SERVICE_NAME
) != NULL
));
778 main(int argc
, char *argv
[])
780 struct wpa_supplicant wpa_s
;
783 dlpi_handle_t dh
= NULL
;
784 datalink_id_t linkid
;
785 dladm_phys_attr_t dpa
;
788 char door_file
[MAXPATHLEN
];
789 dladm_handle_t handle
;
791 if (!is_smf_context()) {
792 (void) fprintf(stderr
,
793 "wpad is an smf(5) managed service and cannot be run from "
794 "the command line; please use dladm(1M).\n");
795 return (SMF_EXIT_ERR_NOSMF
);
799 c
= getopt(argc
, argv
, "i:k:");
810 return (SMF_EXIT_ERR_CONFIG
);
815 * key name is required to retrieve PSK value through libwdladm APIs.
816 * key is saved by dladm command by keyname
819 if ((link
== NULL
) || (key
== NULL
)) {
820 wpa_printf(MSG_ERROR
, "\nLink & key is required.");
824 if ((strlen(key
) >= sizeof (wpa_s
.kname
))) {
825 wpa_printf(MSG_ERROR
, "Too long key name '%s'.", key
);
833 * Hold this link open to prevent a link renaming operation.
835 if (dlpi_open(link
, &dh
, 0) != DLPI_SUCCESS
) {
836 wpa_printf(MSG_ERROR
, "Failed to open link '%s'.", link
);
840 /* This handle is stored in wpa_s when that struct is filled. */
841 if (dladm_open(&handle
) != DLADM_STATUS_OK
) {
842 wpa_printf(MSG_ERROR
, "Failed to open dladm handle");
847 if (dladm_name2info(handle
, link
, &linkid
, NULL
, NULL
, NULL
) !=
849 wpa_printf(MSG_ERROR
, "Invalid link name '%s'.", link
);
856 * Get the device name of the link, which will be used as the door
857 * file name used to communicate with the driver. Note that different
858 * links use different doors.
860 if (dladm_phys_info(handle
, linkid
, &dpa
, DLADM_OPT_ACTIVE
) !=
862 wpa_printf(MSG_ERROR
,
863 "Failed to get device name of link '%s'.", link
);
868 (void) snprintf(door_file
, MAXPATHLEN
, "%s_%s", WPA_DOOR
, dpa
.dp_dev
);
870 (void) memset(&wpa_s
, 0, sizeof (wpa_s
));
871 wpa_s
.driver
= &wpa_driver_wifi_ops
;
872 wpa_s
.handle
= handle
;
873 wpa_s
.linkid
= linkid
;
874 (void) strlcpy(wpa_s
.kname
, key
, sizeof (wpa_s
.kname
));
878 * Setup default WPA/WPA2 configuration
879 * get ESSID and PSK value
881 wpa_s
.conf
= wpa_config_read(&wpa_s
);
882 if (wpa_s
.conf
== NULL
|| wpa_s
.conf
->ssid
== NULL
) {
883 wpa_printf(MSG_ERROR
, "\nNo networks (SSID) configured.\n");
891 * Setup door file to communicate with driver
893 if (wpa_supplicant_door_setup(&wpa_s
, door_file
) != 0) {
894 wpa_printf(MSG_ERROR
, "Failed to setup door(%s)", door_file
);
899 wpa_s
.renew_snonce
= 1;
900 if (wpa_supplicant_driver_init(link
, &wpa_s
) < 0) {
906 * This link is hold again in wpa_supplicant_driver_init(), so that
907 * we release the first reference.
912 wpa_printf(MSG_DEBUG
, "=> eloop_run");
914 (void) eloop_register_signal(SIGINT
, wpa_supplicant_terminate
, NULL
);
915 (void) eloop_register_signal(SIGTERM
, wpa_supplicant_terminate
, NULL
);
916 (void) eloop_register_signal(SIGKILL
, wpa_supplicant_terminate
, NULL
);
920 wpa_printf(MSG_DEBUG
, "<= eloop_run()");
921 wpa_supplicant_disassociate(&wpa_s
, REASON_DEAUTH_LEAVING
);
923 if (wpa_s
.driver
->set_wpa(wpa_s
.handle
, wpa_s
.linkid
, 0) < 0) {
924 wpa_printf(MSG_ERROR
, "Failed to disable WPA in the driver.\n");
928 wpa_supplicant_door_destroy(door_file
);
929 /* The libdladm handle is closed in the following method */
930 wpa_supplicant_cleanup(&wpa_s
);