summaryrefslogtreecommitdiffstats
path: root/mdk-stage1/wireless.c
blob: 2fde04f8460d540d718f8395eef24cd71399f785 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
/*
 * Olivier Blin (oblin)
 * Martin Whitaker (martinw)
 *
 * Copyright 2005 Mandriva
 * Copyright 2020 Mageia
 *
 * This software may be freely redistributed under the terms of the GNU
 * public license.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <linux/types.h>
#include <linux/if.h>
#include <linux/wireless.h>

#include "automatic.h"
#include "stage1.h"
#include "log.h"
#include "utils.h"
#include "wireless.h"

#define WPA_SUPPLICANT_CONF	"/etc/wpa_supplicant.conf"
#define WPA_SUPPLICANT_CTRL	"/var/run/wpa_supplicant"
#define WPA_SUPPLICANT_LOG	"/var/log/wpa_supplicant.log"
#define WPA_SUPPLICANT_PID	"/var/run/wpa_supplicant.pid"

int wireless_open_socket()
{
	return socket(AF_INET, SOCK_DGRAM, 0);
}

int wireless_close_socket(int socket)
{
	return close(socket);
}

static int wireless_ioctl(int socket, const char *ifname, int request, struct iwreq *wrq)
{
	strncpy(wrq->ifr_name, ifname, IFNAMSIZ);
	return ioctl(socket, request, wrq);
}

int wireless_is_aware(int socket, const char *ifname)
{
	struct iwreq wrq;
	return wireless_ioctl(socket, ifname, SIOCGIWNAME, &wrq) == 0;
}

enum return_type configure_wireless(const char *ifname)
{
	enum return_type results;
	char * security[] = { "No security", "WEP", "WPA/WPA2 Personal", NULL };
	char * security_auto[] = { "none", "wep", "wpa_psk", NULL };
	char * choice = NULL;
	char * message = NULL;
	char * questions[] = { "ESSID", "", NULL };
	char * questions_auto[] = { "essid", "" };
	char * key_mgmt = NULL;
	static char ** answers = NULL;
	FILE * fd;
	char cmd[256];
	int status;

	int wsock = wireless_open_socket();
	if (!wireless_is_aware(wsock, ifname)) {
		log_message("interface %s doesn't support wireless", ifname);
		wireless_close_socket(wsock);
		return RETURN_OK;
	}
	wireless_close_socket(wsock);

	results = ask_from_list_auto("Please select your wireless security mode.",
				     security, &choice, "wireless_security", security_auto);
	if (results != RETURN_OK) {
		return RETURN_BACK;
	}

	if (streq(choice, security[2])) {
		message = "Please enter your wireless settings. "
			  "The ESSID is your wireless network identifier. "
			  "The passphrase must be a string of between 8 and 63 ASCII characters.";
		questions[1] = "passphrase";
		questions_auto[1] = "wpa_psk";
		key_mgmt = "WPA-PSK";
	} else if (streq(choice, security[1])) {
		message = "Please enter your wireless settings. "
			  "The ESSID is your wireless network identifier. "
			  "The WEP key must be either a string of 10 or 26 hexadecimal digits, without any separators, "
			  "or a string of 5 or 13 ASCII characters enclosed in double quote marks (e.g. \"12345\").";
		questions[1] = "WEP key";
		questions_auto[1] = "wep_key";
		key_mgmt = "NONE";
	} else {
		message = "Please enter your wireless settings. "
			  "The ESSID is your wireless network identifier.";
		questions[1] = NULL;
		questions_auto[1] = NULL;
		key_mgmt = "NONE";
	}
	results = ask_from_entries_auto(message, questions, &answers, 32, questions_auto, NULL);
	if (results != RETURN_OK) {
		return RETURN_BACK;
	}

	fd = fopen(WPA_SUPPLICANT_PID, "r");
	if (fd) {
		unsigned pid = 0;
		unsigned count = fscanf(fd, "%u", &pid);
		fclose(fd);
		if (count == 1 && pid > 1) {
			log_message("terminating wpa_supplicant (pid %u)", pid);
			kill(pid, SIGQUIT);
			sleep(1);
		}
	}

	fd = fopen(WPA_SUPPLICANT_CONF, "w");
	if (fd == NULL) {
		stg1_error_message("unable to create " WPA_SUPPLICANT_CONF ": %s", strerror(errno));
		return RETURN_ERROR;
	}
	fprintf(fd, "ctrl_interface=" WPA_SUPPLICANT_CTRL "\n");
	fprintf(fd, "ap_scan=1\n");
	fprintf(fd, "network={\n");
	fprintf(fd, "  key_mgmt=%s\n", key_mgmt);
	fprintf(fd, "  scan_ssid=1\n");
	fprintf(fd, "  ssid=\"%s\"\n", answers[0]);
	if (streq(choice, security[2])) {
		fprintf(fd, "  psk=\"%s\"\n", answers[1]);
	} else if (streq(choice, security[1])) {
		fprintf(fd, "  wep_key0=%s\n", answers[1]);
	}
	fprintf(fd, "}\n");
	fclose(fd);

	snprintf(cmd, sizeof(cmd), "/usr/sbin/wpa_supplicant -D nl80211,wext -B -i %s -c %s -f %s -P %s",
		 ifname, WPA_SUPPLICANT_CONF, WPA_SUPPLICANT_LOG, WPA_SUPPLICANT_PID);
	log_message("running %s", cmd);
	status = system(cmd);
	if (status != 0) {
		stg1_error_message("unable to start wpa_supplicant daemon for interface \"%s\": %d", ifname, status);
		return RETURN_ERROR;
	}

	return RETURN_OK;
}