1/*
2 * This is a reverse-engineered driver for mobile WiMAX (802.16e) devices
3 * based on GCT Semiconductor GDM7213 & GDM7205 chip.
4 * Copyright (�) 2010 Yaroslav Levandovsky <leyarx@gmail.com>
5 *
6 * Based on  madWiMAX driver writed by Alexander Gordeev
7 * Copyright (C) 2008-2009 Alexander Gordeev <lasaine@lvk.cs.msu.su>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24#include <errno.h>
25#include <fcntl.h>
26#include <getopt.h>
27#include <poll.h>
28#include <signal.h>
29#include <string.h>
30#include <stdio.h>
31#include <stdint.h>  //typedef
32#include <stdlib.h>
33#include <unistd.h>
34#include <sys/stat.h> // for mkdir
35#include <sys/time.h>
36#include <sys/wait.h>
37
38#include <libusb/libusb.h>
39
40#include "logging.h"
41#include "protocol.h"
42#include "wimax.h"
43#include "tap_dev.h"
44
45#include "eap_auth.h"
46
47#ifdef WITH_DBUS
48	#include <dbus/dbus.h>
49#endif /* WITH_DBUS */
50
51#include <openssl/sha.h>
52#include <openssl/aes.h>
53#include "zlib.h"
54/* variables for the command-line parameters */
55
56static int daemonize = 0;
57
58struct timeval start_sec, curr_sec; // get link status every second
59
60#define QUOTE(name) #name
61#define STR(macro) QUOTE(macro)
62
63#define CONF_DIR STR(CONFDIR)
64
65static char *event_script = CONF_DIR"/event.sh";
66static char *conf_file = "";
67static FILE *logfile = NULL;
68static FILE *xml_file = NULL;
69char *pid_file = NULL;
70
71#define MATCH_BY_LIST		0
72#define MATCH_BY_VID_PID	1
73#define MATCH_BY_BUS_DEV	2
74
75//static int match_method = MATCH_BY_LIST;
76
77/* for matching by list...
78typedef struct usb_device_id_t {
79	unsigned short vendorID;
80	unsigned short productID;
81	unsigned short targetVID;
82	unsigned short targetPID;
83} usb_device_id_t; */
84
85/* list of all known devices
86static usb_device_id_t wimax_dev_ids[] = {
87	{ 0x04e8, 0x6761 },
88	{ 0x04e9, 0x6761 },
89	{ 0x04e8, 0x6731 },
90	{ 0x04e8, 0x6780 },
91};*/
92
93/* for other methods of matching...
94static union {
95	struct {
96		unsigned short vid;
97		unsigned short pid;
98	};
99	struct {
100		unsigned int bus;
101		unsigned int dev;
102	};
103} match_params;*/
104
105/* USB-related parameters */
106
107#define IF_DVD			0
108
109#define EP_IN			(130 | LIBUSB_ENDPOINT_IN)
110#define EP_OUT			(1 | LIBUSB_ENDPOINT_OUT)
111
112#define MAX_PACKET_LEN		0x4000
113
114/* information collector */
115static struct wimax_dev_status wd_status;
116
117enum wimax_state {
118	WS_DEV_NOT_FOUND = 1,	// - Device not found
119	WS_DEV_FOUND,			//  - Device found
120	WS_ERR_INIT_DRIVER,		// - Error init driver
121	WS_RECEIVE_IP,			// - Receive ip-address (event script)
122	WS_SCAN,				// - Search network
123	WS_NET_NOT_FOUND,		// - Network not found
124	WS_NET_FOUND,			// - Network found
125	WS_CON_ERR,				// - Connection error
126	WS_START_AUTH,			// - Start Authentication
127	WS_AUTH_FAILED,			// - Authentication Failed
128	WS_DL_XML_START,		// - Download XML image started
129	WS_DL_XML_END,			// - Download XML image succeed
130};
131
132static
133const struct {
134	int value;
135	const char *name;
136} wimax_state_names_vals[] = {
137	{ WS_DEV_NOT_FOUND, 	"Device not found" },
138	{ WS_DEV_FOUND, 		"Device found" },
139	{ WS_ERR_INIT_DRIVER, 	"Error init driver" },
140	{ WS_RECEIVE_IP, 		"Receive ip-address (event script)" },
141	{ WS_SCAN, 				"Search network" },
142	{ WS_NET_NOT_FOUND, 	"No Signal" },
143	{ WS_NET_FOUND, 		"Network found" },
144	{ WS_CON_ERR, 			"Connection error" },
145	{ WS_START_AUTH, 		"Start Authentication" },
146	{ WS_AUTH_FAILED, 		"Authentication Failed" },
147	{ WS_DL_XML_START, 		"Download XML image started" },
148	{ WS_DL_XML_END, 		"Download XML image succeed" },
149	{ 0, NULL }
150};
151
152const char * wimax_state_to_name(enum wimax_state state)
153{
154	size_t itr, max;
155
156	for(max = 0;;max++)
157		if (wimax_state_names_vals[max].name == NULL)
158			break;
159
160	for (itr = 0; itr < max; itr++)
161		if (wimax_state_names_vals[itr].value == state)
162			return wimax_state_names_vals[itr].name;
163	return NULL;
164}
165
166//char *wimax_states[] = {"INIT", "SYNC", "NEGO", "NORMAL", "SLEEP", "IDLE", "HHO", "FBSS", "RESET", "RESERVED", "UNDEFINED", "BE", "NRTPS", "RTPS", "ERTPS", "UGS", "INITIAL_RNG", "BASIC", "PRIMARY", "SECONDARY", "MULTICAST", "NORMAL_MULTICAST", "SLEEP_MULTICAST", "IDLE_MULTICAST", "FRAG_BROADCAST", "BROADCAST", "MANAGEMENT", "TRANSPORT"};
167
168/* libusb stuff */
169static struct libusb_context *ctx = NULL;
170static struct libusb_device_handle *devh = NULL;
171static struct libusb_transfer *req_transfer = NULL;
172static int kernel_driver_active = 0;
173
174static unsigned char read_buffer[MAX_PACKET_LEN];
175
176static int tap_fd = -1;
177static char tap_dev[20] = "wimax%d";
178static int tap_if_up = 0;
179
180static nfds_t nfds;
181static struct pollfd* fds = NULL;
182
183static int device_disconnected = 0;
184
185static void exit_release_resources(int code);
186static void dbus_conn_info_send(enum wimax_state); // int signal_code
187static void dbus_sig_info_send(void);
188static void dbus_dev_info_send(void);
189static void dbus_bsid_info_send(void);
190static void dbus_percent_info_send(short, short);
191
192#define CHECK_NEGATIVE(x) {if((r = (x)) < 0) return r;}
193#define CHECK_DISCONNECTED(x) {if((r = (x)) == LIBUSB_ERROR_NO_DEVICE) exit_release_resources(0);}
194
195int dbus_use = 0;
196
197#ifdef WITH_DBUS
198DBusConnection *dbus_connection;
199DBusError dbus_error;
200#endif /* WITH_DBUS */
201
202//DBusGConnection *dbus_connection;
203//GError *dbus_error;
204//DBusGProxy *dbus_proxy;
205/*
206static struct libusb_device_handle* find_wimax_device(void)
207{
208	struct libusb_device **devs;
209	struct libusb_device *found = NULL;
210	struct libusb_device *dev;
211	struct libusb_device_handle *handle = NULL;
212	int i = 0;
213	int r;
214
215	if (libusb_get_device_list(ctx, &devs) < 0)
216		return NULL;
217
218	while (!found && (dev = devs[i++]) != NULL) {
219		struct libusb_device_descriptor desc;
220		unsigned int j = 0;
221		unsigned short dev_vid, dev_pid;
222
223		r = libusb_get_device_descriptor(dev, &desc);
224		if (r < 0) {
225			continue;
226		}
227		dev_vid = libusb_le16_to_cpu(desc.idVendor);
228		dev_pid = libusb_le16_to_cpu(desc.idProduct);
229		wmlog_msg(1, "Bus %03d Device %03d: ID %04x:%04x", libusb_get_bus_number(dev), libusb_get_device_address(dev), dev_vid, dev_pid);
230		switch (match_method) {
231			case MATCH_BY_LIST: {
232				for (j = 0; j < sizeof(wimax_dev_ids) / sizeof(usb_device_id_t); j++) {
233					if (dev_vid == wimax_dev_ids[j].vendorID && dev_pid == wimax_dev_ids[j].productID) {
234						found = dev;
235						break;
236					}
237				}
238				break;
239			}
240			case MATCH_BY_VID_PID: {
241				if (dev_vid == match_params.vid && dev_pid == match_params.pid) {
242					found = dev;
243				}
244				break;
245			}
246			case MATCH_BY_BUS_DEV: {
247				if (libusb_get_bus_number(dev) == match_params.bus && libusb_get_device_address(dev) == match_params.dev) {
248					found = dev;
249				}
250				break;
251			}
252		}
253	}
254
255	if (found) {
256		r = libusb_open(found, &handle);
257		if (r < 0)
258			handle = NULL;
259	}
260
261	libusb_free_device_list(devs, 1);
262	return handle;
263}
264*/
265static int switch_wimax_device(void)
266{
267	struct libusb_device_handle *handle = NULL;
268	int r;
269	handle = libusb_open_device_with_vid_pid(ctx, 0x1076, 0x7f40);
270	if (handle != NULL ){
271		int disk_if = 0;
272
273		if (libusb_kernel_driver_active(handle, disk_if) == 1)
274		{
275			r = libusb_detach_kernel_driver(handle, disk_if);
276			if (r < 0){
277				wmlog_msg(1, "Kernel driver detaching (error %d)", r);
278			} else {
279				wmlog_msg(1, "Kernel driver deteched!");
280			}
281		} else if (libusb_kernel_driver_active(handle, 1) == 1)
282		{
283			r = libusb_detach_kernel_driver(handle, 1);
284			disk_if = 1;
285			if (r < 0){
286				wmlog_msg(1, "Kernel driver detaching (error %d)", r);
287			} else {
288				wmlog_msg(1, "Kernel driver deteched!");
289			}
290		}
291
292		r = libusb_claim_interface(handle, disk_if);
293		if (r < 0) {
294			disk_if = 1;
295			r = libusb_claim_interface(handle, disk_if);
296		}
297		if (r < 0) {
298			wmlog_msg(1, "Claim Interface problems (error %d)", r);
299		}
300		else
301		{
302			wmlog_msg(1, "Innterface claimed");
303				r = libusb_control_transfer(handle, 0xa1, 0xa0, 0, disk_if, read_buffer, 1, 1000);
304			wmlog_msg(1, "Sending Control message (result %d - %s)", r, r ? "bad" : "ok");
305				libusb_release_interface(handle, disk_if);
306				libusb_close(handle);
307		}
308		return 1;
309	}
310	return 0;
311}
312
313// ***Edited by fanboy***
314static struct libusb_device_handle* find_wimax_device(void)
315{
316	struct libusb_device_handle *handle = NULL;
317
318	//Switch modem the same as in usb_modeswitch
319	handle = libusb_open_device_with_vid_pid(ctx, 0x1076, 0x7f00);
320	if (handle == NULL){
321		if (switch_wimax_device()){
322
323			int retry = 0;
324			do
325			{
326				sleep(1); // Wait while device switching
327				handle = libusb_open_device_with_vid_pid(ctx, 0x1076, 0x7f00);
328			}
329			while (retry++ < 5 && !handle);
330
331			if (handle) wmlog_msg(2, "Device switched after %d retries.", retry);
332			else  wmlog_msg(1, "Device not switched after %d retries.", retry);
333		}
334	}
335	return handle;
336}
337
338static void get_wimax_device(void)
339{
340	int r;
341
342	devh = find_wimax_device();
343	if (devh == NULL) {
344		if (dbus_use) dbus_conn_info_send(WS_DEV_NOT_FOUND);
345		wmlog_msg(0, "Could not find/open device");
346		exit_release_resources(1);
347	}
348	if (dbus_use) dbus_conn_info_send(WS_DEV_FOUND);
349	wmlog_msg(0, "Device found");
350	if (libusb_kernel_driver_active(devh, IF_DVD) == 1) {
351		kernel_driver_active = 1;
352		r = libusb_detach_kernel_driver(devh, IF_DVD);
353		if (r < 0) {
354			wmlog_msg(0, "kernel driver detach error %d", r);
355		} else {
356			wmlog_msg(0, "detached modem kernel driver");
357		}
358	}
359
360	r = libusb_claim_interface(devh, 0);
361	if (r < 0) {
362		if (dbus_use) dbus_conn_info_send(WS_DEV_NOT_FOUND);
363		wmlog_msg(0, "Claim usb interface error %d", r);
364		exit_release_resources(1);
365	}
366	wmlog_msg(0, "Claimed interface");
367}
368
369static int set_data(unsigned char* data, int size)
370{
371	int r;
372	int transferred;
373
374	wmlog_dumphexasc(3, data, size, "Bulk write:");
375
376	r = libusb_bulk_transfer(devh, EP_OUT, data, size, &transferred, 0);
377	if (r < 0) {
378		wmlog_msg(1, "bulk write error %d", r);
379		if (r == LIBUSB_ERROR_NO_DEVICE) {
380			if (dbus_use) dbus_conn_info_send(WS_DEV_NOT_FOUND);
381			exit_release_resources(0);
382		}
383		return r;
384	}
385	if (transferred < size) {
386		wmlog_msg(1, "short write (%d)", r);
387		return -1;
388	}
389	return r;
390}
391
392void eap_server_rx(unsigned char *data, int data_len) // Sent data from peer to server
393{
394	unsigned char req_data[MAX_PACKET_LEN];
395	int len;
396
397	len = fill_eap_server_rx_req(req_data, data, data_len);
398	set_data(req_data, len);
399}
400
401void eap_key(unsigned char *data, int data_len)
402{
403	unsigned char req_data[MAX_PACKET_LEN];
404	int len;
405
406	len = fill_eap_key_req(req_data, data, data_len);
407	set_data(req_data, len);
408}
409
410static void cb_req(struct libusb_transfer *transfer)
411{
412	if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
413		wmlog_msg(1, "async bulk read error %d", transfer->status);
414		if (transfer->status == LIBUSB_TRANSFER_NO_DEVICE) {
415			device_disconnected = 1;
416			return;
417		}
418	} else {
419		wmlog_dumphexasc(3, transfer->buffer, transfer->actual_length, "Async read:");
420		process_response(&wd_status, transfer->buffer, transfer->actual_length);
421	}
422	if (libusb_submit_transfer(req_transfer) < 0) {
423		wmlog_msg(1, "async read transfer sumbit failed");
424	}
425}
426
427/* get link_status *//*
428int get_link_status()
429{
430	return wd_status.link_status;
431}*/
432
433/* set close-on-exec flag on the file descriptor */
434int set_coe(int fd)
435{
436	int flags;
437
438	flags = fcntl(fd, F_GETFD);
439	if (flags == -1)
440	{
441		wmlog_msg(1, "failed to set close-on-exec flag on fd %d", fd);
442		return -1;
443	}
444	flags |= FD_CLOEXEC;
445	if (fcntl(fd, F_SETFD, flags) == -1)
446	{
447		wmlog_msg(1, "failed to set close-on-exec flag on fd %d", fd);
448		return -1;
449	}
450
451	return 0;
452}
453
454/* run specified script */
455static int raise_event(char *event)
456{
457	int pid = fork();
458
459	if(pid < 0) { /* error */
460		return -1;
461	} else if (pid > 0) { /* parent */
462		return pid;
463	} else { /* child */
464		char *args[] = {event_script, event, tap_dev, NULL};
465		char *env[1] = {NULL};
466		/* run the program */
467		execve(args[0], args, env);
468		exit(1);
469	}
470}
471
472/* brings interface up and runs a user-supplied script */
473static int if_create()
474{
475	tap_fd = tap_open(tap_dev);
476	if (tap_fd < 0) {
477		wmlog_msg(0, "failed to allocate tap interface");
478		wmlog_msg(0,
479				"You should have TUN/TAP driver compiled in the kernel or as a kernel module.\n"
480				"If 'modprobe tun' doesn't help then recompile your kernel.");
481		exit_release_resources(1);
482	}
483	tap_set_hwaddr(tap_fd, tap_dev, wd_status.mac);
484	tap_set_mtu(tap_fd, tap_dev, 1386);
485	set_coe(tap_fd);
486	wmlog_msg(0, "Allocated tap interface: %s", tap_dev);
487	wmlog_msg(2, "Starting if-create script...");
488	raise_event("if-create");
489	return 0;
490}
491
492/* brings interface up and runs a user-supplied script */
493static int if_up()
494{
495	tap_bring_up(tap_fd, tap_dev);
496	wmlog_msg(2, "Starting if-up script...");
497	raise_event("if-up");
498	tap_if_up = 1;
499	if (dbus_use) {
500		dbus_conn_info_send(WS_RECEIVE_IP);
501		dbus_bsid_info_send();
502	}
503	return 0;
504}
505
506/* brings interface down and runs a user-supplied script */
507static int if_down()
508{
509	if (!tap_if_up) return 0;
510	tap_if_up = 0;
511	wmlog_msg(2, "Starting if-down script...");
512	raise_event("if-down");
513	tap_bring_down(tap_fd, tap_dev);
514	return 0;
515}
516
517/* brings interface down and runs a user-supplied script */
518static int if_release()
519{
520	wmlog_msg(2, "Starting if-release script...");
521	raise_event("if-release");
522	tap_close(tap_fd, tap_dev);
523	return 0;
524}
525
526/* set link_status *//*
527void set_link_status(int link_status)
528{
529	wd_status.info_updated |= WDS_LINK_STATUS;
530
531	if (wd_status.link_status == link_status) return;
532
533	if (wd_status.link_status < 2 && link_status == 2) {
534		if_up();
535	}
536	if (wd_status.link_status == 2 && link_status < 2) {
537		if_down();
538	}
539	if (link_status == 1) {
540		first_nego_flag = 1;
541	}
542
543	wd_status.link_status = link_status;
544}*/
545
546/* get state *//*
547int get_state()
548{
549	return wd_status.state;
550}*/
551
552/* set state *//*
553void set_state(int state)
554{
555	wd_status.state = state;
556	wd_status.info_updated |= WDS_STATE;
557	if (state >= 1 && state <= 3 && wd_status.link_status != (state - 1)) {
558		set_link_status(state - 1);
559	}
560}*/
561
562static int alloc_transfers(void)
563{
564	req_transfer = libusb_alloc_transfer(0);
565	if (!req_transfer)
566		return -ENOMEM;
567
568	libusb_fill_bulk_transfer(req_transfer, devh, EP_IN, read_buffer,
569		sizeof(read_buffer), cb_req, NULL, 0);
570
571	return 0;
572}
573
574int write_netif(const void *buf, int count)
575{
576	return tap_write(tap_fd, buf, count);
577}
578
579static int read_tap()
580{
581	unsigned char buf[MAX_PACKET_LEN];
582	int hlen = get_header_len();
583	int r;
584	int len;
585
586	r = tap_read(tap_fd, buf + hlen, MAX_PACKET_LEN - hlen);
587
588	if (r < 0)
589	{
590		wmlog_msg(1, "Error while reading from TAP interface");
591		return r;
592	}
593
594	if (r == 0)
595	{
596		return 0;
597	}
598
599	len = fill_data_packet_header(buf, r);
600	wmlog_dumphexasc(4, buf, len, "Outgoing packet:");
601	r = set_data(buf, len);
602
603	return r;
604}
605
606static int process_events_once(int timeout)
607{
608	struct timeval tv = {0, 0};
609	int r;
610	int libusb_delay;
611	int delay;
612	unsigned int i;
613	char process_libusb = 0;
614
615	r = libusb_get_next_timeout(ctx, &tv);
616	if (r == 1 && tv.tv_sec == 0 && tv.tv_usec == 0)
617	{
618		r = libusb_handle_events_timeout(ctx, &tv);
619	}
620
621	delay = libusb_delay = tv.tv_sec * 1000 + tv.tv_usec;
622	if (delay <= 0 || delay > timeout)
623	{
624		delay = timeout;
625	}
626
627	CHECK_NEGATIVE(poll(fds, nfds, delay));
628
629	process_libusb = (r == 0 && delay == libusb_delay);
630
631	for (i = 0; i < nfds; ++i)
632	{
633		if (fds[i].fd == tap_fd) {
634			if (fds[i].revents)
635			{
636				CHECK_NEGATIVE(read_tap());
637			}
638			continue;
639		}
640		process_libusb |= fds[i].revents;
641	}
642
643	if (process_libusb)
644	{
645		struct timeval tv = {.tv_sec = 0, .tv_usec = 0};
646		CHECK_NEGATIVE(libusb_handle_events_timeout(ctx, &tv));
647	}
648
649	return 0;
650}
651
652/* handle events until timeout is reached or all of the events in event_mask happen */
653static int process_events_by_mask(int timeout, unsigned int event_mask)
654{
655	struct timeval start, curr;
656	int r;
657	int delay = timeout;
658
659	CHECK_NEGATIVE(gettimeofday(&start, NULL));
660
661	wd_status.info_updated &= ~event_mask;
662
663	while ((event_mask == 0 || (wd_status.info_updated & event_mask) != event_mask) && delay >= 0) {
664		long a;
665
666		CHECK_NEGATIVE(process_events_once(delay));
667
668		if (device_disconnected) {
669			if (dbus_use) dbus_conn_info_send(WS_DEV_NOT_FOUND);
670			exit_release_resources(0);
671		}
672
673		CHECK_NEGATIVE(gettimeofday(&curr, NULL));
674
675		a = (curr.tv_sec - start.tv_sec) * 1000 + (curr.tv_usec - start.tv_usec) / 1000;
676		delay = timeout - a;
677	}
678
679	wd_status.info_updated &= ~event_mask;
680
681	return (delay > 0) ? delay : 0;
682}
683
684int alloc_fds()
685{
686	int i;
687	const struct libusb_pollfd **usb_fds = libusb_get_pollfds(ctx);
688
689	if (!usb_fds)
690	{
691		return -1;
692	}
693
694	nfds = 0;
695	while (usb_fds[nfds])
696	{
697		nfds++;
698	}
699	if (tap_fd != -1) {
700		nfds++;
701	}
702
703	if(fds != NULL) {
704		free(fds);
705	}
706
707	fds = (struct pollfd*)calloc(nfds, sizeof(struct pollfd));
708	for (i = 0; usb_fds[i]; ++i)
709	{
710		fds[i].fd = usb_fds[i]->fd;
711		fds[i].events = usb_fds[i]->events;
712		set_coe(usb_fds[i]->fd);
713	}
714	if (tap_fd != -1) {
715		fds[i].fd = tap_fd;
716		fds[i].events = POLLIN;
717		fds[i].revents = 0;
718	}
719
720	free(usb_fds);
721
722	return 0;
723}
724
725void cb_add_pollfd(int fd, short events, void *user_data)
726{
727	alloc_fds();
728}
729
730void cb_remove_pollfd(int fd, void *user_data)
731{
732	alloc_fds();
733}
734
735static void dm_cmd(char *cmd)
736{
737	unsigned char req_data[MAX_PACKET_LEN];
738	int len;
739	len = fill_dm_cmd_req(req_data, cmd);
740	set_data(req_data, len);
741}
742
743static void DL_xml_image()
744{
745	unsigned char req_data[MAX_PACKET_LEN];
746	unsigned char data[0x400];
747	int len, data_len, offset, size;
748	int r;
749
750	r = libusb_init(&ctx);
751	if (r < 0) {
752		wmlog_msg(0, "failed to initialise libusb");
753		exit(1);
754	}
755
756	get_wimax_device();
757	alloc_transfers();
758
759	wmlog_msg(2, "Continuous async read start...");
760	CHECK_DISCONNECTED(libusb_submit_transfer(req_transfer));
761
762	fseek(xml_file, 0L, SEEK_END);
763	size = ftell(xml_file);
764	wmlog_msg(0, "XML Image size: %d",size);
765	fseek(xml_file, 0L, SEEK_SET);
766
767	if (dbus_use) dbus_conn_info_send(WS_DL_XML_START);
768	offset = 0;
769	while (offset != 0xffffffff)
770	{
771		data_len = fread(data, 1, 0x400, xml_file);
772		if (data_len == 0)
773		{
774			if (!feof(xml_file))
775				wmlog_msg(0, "bad EOF");
776			offset = 0xffffffff;
777			if (dbus_use) dbus_percent_info_send(0x0100, 100);
778		}
779		else
780		{
781			if (dbus_use) dbus_percent_info_send(0x0100, offset * 100 / size);
782		}
783		len = fill_image_dl_req(req_data, 0x0100, offset, data, data_len);
784//		wmlog_msg(0, "percent %d",offset * 100 / size);
785		offset += data_len;
786		set_data(req_data, len);
787		process_events_by_mask(500, WDS_CERT);
788	}
789	if (dbus_use) dbus_conn_info_send(WS_DL_XML_END);
790	fclose(xml_file);
791
792	dm_cmd("reboot");
793
794	exit_release_resources(1);
795}
796
797
798static
799void AES_cbc_decrypt(uint8_t *shakey, uint8_t *inbuf, uint8_t *outbuf)
800{
801	unsigned char iv[16] = {0x43,0x6c,0x61,0x72,0x6b,0x4a,0x4a,0x61,0x6e,0x67,0x00,0x00,0x00,0x00,0x00,0x00}; //ClarkJJang
802
803	AES_KEY aeskey;
804
805	AES_set_decrypt_key(shakey, 24*8, &aeskey); //192
806
807	AES_cbc_encrypt(inbuf, outbuf, 16, &aeskey, iv, AES_DECRYPT);
808}
809
810
811static
812int decrypt_data(unsigned char *buf, unsigned char *outbuf, int len)
813{
814	int i, dec_buf_len;
815	uint8_t key_sha[0x18];
816	uint8_t dec_buf[len];
817
818	memset(key_sha,0x00,sizeof(key_sha));
819	memset(dec_buf,0x00,sizeof(dec_buf));
820
821	SHA1(wd_status.mac, 6, key_sha);
822
823	for (i = 0; i < (len / 16); i++)
824		AES_cbc_decrypt(key_sha, buf + 16 * i, dec_buf + 16 * i);
825	dec_buf_len = (dec_buf[0] << 24) + (dec_buf[1] << 16) + (dec_buf[2] << 8) + dec_buf[3];
826	memcpy(outbuf, dec_buf + 4, dec_buf_len);
827
828	wmlog_msg(2, "Decrypted size is %d bytes.", dec_buf_len);
829	return dec_buf_len;
830}
831
832
833static
834int extract_cert(unsigned char *buf, int len, char *path)
835{
836	int dec_buf_len, gz_len;
837	char gz_path[0x100]; //, pem_path[0x100]
838	uint8_t dec_buf[len], gz_buf[MAX_PACKET_LEN];
839	FILE *fp;
840	voidp gz;
841
842	memset(dec_buf,0x00,sizeof(dec_buf));
843
844	dec_buf_len = decrypt_data(buf,  dec_buf, len);
845	wmlog_msg(2, "Cert decrypted");
846
847	sprintf(gz_path,"%s.gz", path);
848	fp=fopen((char *)gz_path, "wb");
849	if (fp == NULL)
850		return errno;
851	fwrite(dec_buf, 1, dec_buf_len, fp); //dec_buf + 4
852	fclose(fp);
853
854	gz = gzopen(gz_path, "rb");
855	if (gz == NULL)
856		return errno;
857	gz_len = gzread(gz, gz_buf, sizeof(gz_buf));
858	gzclose(gz);
859	remove(gz_path);
860
861	wmlog_msg(2, "Extracted cert size is %d bytes.", gz_len);
862
863		fp=fopen((char *)path, "ab");
864		if (fp == NULL)
865			return errno;
866		fwrite(gz_buf,1,gz_len,fp);
867		fclose(fp);
868
869	return 0;
870}
871
872
873static
874int get_nv_data(short code, unsigned char *buf)
875{
876	unsigned char req_data[MAX_PACKET_LEN];
877	int len, data_len, buf_len = 0;
878
879	memset(wd_status.cert, 0, sizeof(wd_status.cert));
880
881	len = fill_get_data_req_start(req_data, code);
882	set_data(req_data, len);
883
884	process_events_by_mask(2000, WDS_CERT);
885
886	while(1)
887	{
888		if( ((wd_status.cert[0] << 8) + wd_status.cert[1]) ==  code )
889		{
890			if (wd_status.cert[2] != 0xff)
891			{
892				data_len = (wd_status.cert_buf[0] << 8) + wd_status.cert_buf[1];
893
894				memcpy(buf+buf_len,wd_status.cert_buf+2,data_len);
895				buf_len += data_len;
896
897				len = fill_get_data_req_step(req_data, code, buf_len);
898				set_data(req_data, len);
899
900				process_events_by_mask(2000, WDS_CERT);
901			}
902			else break;
903		}
904		else
905			break;
906	}
907
908	return buf_len;
909}
910
911
912static
913void get_cert()
914{
915	int r, i;
916	char path[0x100];
917	sprintf(path,CONF_DIR"/%02x%02x%02x%02x%02x%02x", wd_status.mac[0], wd_status.mac[1], \
918												wd_status.mac[2], wd_status.mac[3], wd_status.mac[4], wd_status.mac[5]);
919
920	r = mkdir(path,S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
921	if (r)
922	{
923		if (errno != EEXIST) //17
924			return;
925	}
926
927	for (i = 0x0101; i <= 0x0106; i++)
928	{
929		if (	(i == 0x0105 && wd_status.config->use_nv == 1) ||
930				(i == 0x0101 && wd_status.config->cert_nv == 1 && wd_status.config->dev_cert_null == 0) ||
931				(i != 0x0101 && i != 0x0105 && wd_status.config->cert_nv == 1 && wd_status.config->ca_cert_null == 0)	)
932		{
933			unsigned char data[MAX_PACKET_LEN];
934			int data_len;
935			data_len = get_nv_data(i, data);
936			if (data_len != 0)
937			{
938
939			switch (i) {
940				case 0x0101:
941				{
942					free(wd_status.config->client_cert);
943					free(wd_status.config->private_key);
944					wd_status.config->client_cert = NULL;
945					wd_status.config->private_key = NULL;
946					wd_status.config->client_cert = (unsigned char *)malloc(strlen(path)+13);
947					sprintf((char *)wd_status.config->client_cert,"%s/client_cert.pem",path);
948					wd_status.config->private_key = (unsigned char *)strdup((char *)wd_status.config->client_cert);
949					r = extract_cert(data, data_len, (char *)wd_status.config->client_cert);
950					if(r) {
951						free(wd_status.config->client_cert);
952						free(wd_status.config->private_key);
953						wd_status.config->client_cert = NULL;
954						wd_status.config->private_key = NULL;
955					}
956					break;
957				}
958					break;
959				case 0x0102:
960				case 0x0103:
961				case 0x0104:
962				case 0x0106:
963				{
964					free(wd_status.config->ca_cert);
965					wd_status.config->ca_cert = NULL;
966					wd_status.config->ca_cert = (unsigned char *)malloc(strlen(path)+13);
967					sprintf((char *)wd_status.config->ca_cert,"%s/root_ca.pem",path);
968					r = extract_cert(data, data_len, (char *)wd_status.config->ca_cert);
969					if(r) {
970						free(wd_status.config->ca_cert);
971						wd_status.config->ca_cert = NULL;
972					}
973					break;
974				}
975				case 0x0105:
976				{
977					data_len = decrypt_data(data, data, data_len);
978					if(data_len) {
979						int j;
980						for (j=0; j < data_len;)
981						{
982							int id, id_len;
983							id = data[j];
984							id_len = (data[j+1] << 8) + data[j+2];
985							if(id_len)
986							{
987								char str[id_len+1];
988								str[id_len] = '\0';
989								memcpy(str, data+j+3, id_len);
990//							wmlog_msg(2, "id: %d String: %s", id, str);
991								switch (id) {
992									case 0x01:
993										free(wd_status.config->anonymous_identity);
994										wd_status.config->anonymous_identity = NULL;
995										wd_status.config->anonymous_identity = (unsigned char *)strdup(str);
996										wd_status.config->anonymous_identity_len = id_len;
997										break;
998									case 0x02:
999										if (wd_status.config->cert_nv == 1 &&
1000												wd_status.config->dev_cert_null == 0) {
1001											free(wd_status.config->private_key_passwd);
1002											wd_status.config->private_key_passwd = NULL;
1003											wd_status.config->private_key_passwd = (unsigned char *)strdup(str);
1004										}
1005										break;
1006									case 0x03:
1007										free(wd_status.config->identity);
1008										wd_status.config->identity = NULL;
1009										wd_status.config->identity = (unsigned char *)strdup(str);
1010										wd_status.config->identity_len = id_len;
1011										break;
1012									case 0x04:
1013										free(wd_status.config->password);
1014										wd_status.config->password = NULL;
1015										wd_status.config->password = (unsigned char *)strdup(str);
1016										wd_status.config->password_len = id_len;
1017										break;
1018									default:
1019										wmlog_msg(2, "Unknown EAP param from NV # %02x", id);
1020										break;
1021								}
1022							}
1023							j += id_len + 3;
1024						}
1025					}
1026					break;
1027				}
1028			}
1029
1030			}
1031		}
1032	}
1033}
1034
1035
1036static int init(void)
1037{
1038	unsigned char req_data[MAX_PACKET_LEN];
1039	int len;
1040	int r;
1041
1042	alloc_transfers();
1043
1044	wmlog_msg(2, "Continuous async read start...");
1045	CHECK_DISCONNECTED(libusb_submit_transfer(req_transfer));
1046
1047	len = fill_rf_off_req(req_data);
1048	set_data(req_data, len);
1049
1050	process_events_by_mask(2000, WDS_RF_STATE);
1051
1052	len = fill_debug_req(req_data);  //mode normal or test
1053	set_data(req_data, len);
1054
1055	len = fill_string_info_req(req_data);
1056	set_data(req_data, len);
1057
1058	process_events_by_mask(500, WDS_CHIP | WDS_FIRMWARE);
1059
1060	wmlog_msg(1, "Chip info: %s", wd_status.chip);
1061	wmlog_msg(1, "Firmware info: %s", wd_status.firmware);
1062
1063	if(wd_status.nspid == 0) {
1064		len = fill_get_nspid_req(req_data);
1065		set_data(req_data, len);
1066		process_events_by_mask(500, WDS_NSPID);
1067	}
1068	wmlog_msg(1, "H-NSPID: 0x%06x", wd_status.nspid);
1069
1070	len = fill_mac_req(req_data);
1071	set_data(req_data, len);
1072
1073	process_events_by_mask(500, WDS_MAC);
1074
1075	wmlog_msg(1, "MAC: %02x:%02x:%02x:%02x:%02x:%02x", wd_status.mac[0], wd_status.mac[1], wd_status.mac[2], wd_status.mac[3], wd_status.mac[4], wd_status.mac[5]);
1076
1077	if (dbus_use) dbus_dev_info_send();
1078
1079	len = fill_rf_on_req(req_data);
1080	set_data(req_data, len);
1081
1082	process_events_by_mask(20000, WDS_RF_STATE);
1083
1084	wmlog_msg(2, "RF ON.");
1085
1086	get_cert();
1087
1088	return 0;
1089}
1090
1091static int scan_loop(void)
1092{
1093	unsigned char req_data[MAX_PACKET_LEN];
1094	int len;
1095	int r;
1096
1097	while (1)
1098	{
1099		if (wd_status.link_status == 0) {
1100
1101			if_down();
1102
1103			if (wd_status.config->use_pkm == 1){
1104				len = fill_auth_on_req(req_data);
1105				set_data(req_data, len);
1106			}
1107
1108			if (dbus_use && wd_status.network_status == 0) dbus_conn_info_send(WS_SCAN);
1109			wmlog_msg(0, "Search network...");
1110			len = fill_find_network_req(req_data, &wd_status);
1111			set_data(req_data, len);
1112
1113			while (process_events_by_mask(60000, WDS_LINK_STATUS) < 0) {;}
1114
1115			if (wd_status.link_status == 0) {
1116				if (dbus_use && wd_status.network_status == 0) dbus_conn_info_send(WS_NET_NOT_FOUND);
1117				wmlog_msg(0, "Network not found.");
1118				wd_status.network_status--;
1119				if (wd_status.network_status < 60)
1120					sleep(30);
1121				else if (wd_status.network_status < 30)
1122					sleep(15);
1123				else if (wd_status.network_status < 10)
1124					sleep(5);
1125			} else {
1126				if (dbus_use) dbus_conn_info_send(WS_NET_FOUND);
1127				wmlog_msg(0, "Network found.");
1128					wd_status.link_status = 0;
1129					wd_status.network_status = 0;
1130				len = fill_connect_req(req_data, &wd_status);
1131				set_data(req_data, len);
1132
1133				while (process_events_by_mask(100000, WDS_LINK_STATUS) < 0) {;}
1134
1135				if (wd_status.link_status == 0) {
1136					if (dbus_use) dbus_conn_info_send(WS_CON_ERR);
1137					wmlog_msg(0, "Connection error.");
1138				} else {
1139					wmlog_msg(0, "Connected to Network.");
1140
1141					wd_status.auth_info = 0; //if more then one BS found.
1142					r = 1;
1143					while (	1 ){
1144						process_events_by_mask(5000, WDS_AUTH_STATE);
1145						wmlog_msg(2, "Auth_state: %06x",wd_status.auth_state);
1146
1147						switch (wd_status.auth_state) {
1148							case 0x0001ff:
1149							case 0x0100ff:
1150							case 0x0101ff:
1151							case 0x0200ff:
1152							case 0x0300ff:
1153							case 0x0301ff:
1154							case 0x0400ff:
1155							case 0x0401ff: {
1156								process_events_by_mask(3000, WDS_LINK_STATUS);
1157								goto auth_loop_done;
1158							}
1159
1160							case 0x020000: {
1161								if (dbus_use) dbus_conn_info_send(WS_START_AUTH);
1162								wmlog_msg(0, "Start Authentication.");
1163								if (eap_peer_init(wd_status.config)< 0) {
1164									wmlog_msg(0, "EAP Peer init error.");
1165									break;
1166								}
1167								r = 1;
1168								wd_status.info_updated = WDS_NONE;
1169								while( r > 0)
1170								{
1171									if (process_events_by_mask(100000, WDS_EAP))
1172										r = eap_peer_step();
1173									else
1174										r = 0;
1175								}
1176								eap_peer_deinit();
1177								break;
1178							}
1179							case 0x0201ff: {
1180								if (dbus_use) dbus_conn_info_send(WS_AUTH_FAILED);
1181								if (wd_status.auth_info == 0){
1182									wmlog_msg(0, "Authentication Failed. Renewing Authentication.");
1183								}
1184								else {
1185									wmlog_msg(0, "Authentication Failed.");
1186									goto auth_loop_done;
1187								}
1188								break;
1189							}
1190							case 0x020100: {
1191								wmlog_msg(0, "Authentication Succeed.");
1192								break;
1193							}
1194							case 0x040100: {
1195								if_up();
1196								process_events_by_mask(2000, WDS_LINK_STATUS);
1197								process_events_by_mask(2000, WDS_LINK_STATUS);
1198								goto auth_loop_done;
1199							}
1200							default: {
1201								break;
1202							}
1203						}
1204					}
1205auth_loop_done:;
1206				}
1207			}
1208
1209		}
1210		else {
1211
1212				len = fill_connection_params_req(req_data);
1213				set_data(req_data, len);
1214
1215				process_events_by_mask(500, WDS_RSSI1 | WDS_CINR1 | WDS_RSSI2 | WDS_CINR2 | WDS_TXPWR | WDS_FREQ);
1216
1217				wmlog_msg(1, "RSSI1: %d   CINR1: %d   TX Power: %d   Frequency: %d",
1218								wd_status.rssi1, wd_status.cinr1, wd_status.txpwr, wd_status.freq);
1219				wmlog_msg(1, "RSSI2: %d   CINR2: %d",
1220								wd_status.rssi2, wd_status.cinr2);
1221
1222				if (dbus_use) dbus_sig_info_send();
1223
1224				process_events_by_mask(5000, WDS_LINK_STATUS);
1225		}
1226	}
1227
1228	return 0;
1229}
1230
1231/* print usage information */
1232void usage(const char *progname)
1233{
1234	printf("Usage: %s [options]\n", progname);
1235	printf("Options:\n");
1236	printf("  -C, --cfg-file=FILE         path to configuration file\n");
1237	printf("      --dl-xml=FILE           DL XML Image & exit\n");
1238	printf("  -D,                         Switch device & exit\n");
1239	printf("  -v,                         verbose log level (even more -vv)\n");
1240	printf("  -p, --pid-file=FILE         PID file (only for daemonize mode)\n");
1241	printf("  -d, --daemonize             daemonize after startup\n");
1242	printf("  -V, --version               print the version number\n");
1243#ifdef WITH_DBUS
1244	printf("      --with-dbus             Run with dbus support\n");
1245#endif
1246	printf("  -h, --help                  display this help\n");
1247}
1248
1249/* print version */
1250void version()
1251{
1252	printf("%s %s\n", "GCTwimax", get_wimax_version());
1253}
1254
1255static void parse_args(int argc, char **argv)
1256{
1257	while (1)
1258	{
1259		int c;
1260		/* getopt_long stores the option index here. */
1261		int option_index = 0;
1262		static struct option long_options[] =
1263		{
1264			{"cfg-file",	required_argument, 	0, 'C'},
1265			{"dl-xml",		required_argument, 	0, 8},
1266			{"daemonize",	no_argument,		0, 'd'},
1267			{"pid-file",	required_argument, 	0, 'p'},
1268			{"version",		no_argument,		0, 'V'},
1269#ifdef WITH_DBUS
1270			{"with-dbus",	no_argument,		0, 7},
1271#endif /* WITH_DBUS */
1272			{"help",		no_argument,		0, 'h'},
1273			{0, 0, 0, 0}
1274		};
1275
1276		c = getopt_long(argc, argv, "C:p:vDdVh", long_options, &option_index);
1277		/* detect the end of the options. */
1278		if (c == -1)
1279			break;
1280
1281		switch (c)
1282		{
1283			case 'C': {
1284					conf_file = optarg;
1285					break;
1286				}
1287			case 'p': {
1288					pid_file = rel2abs_path(optarg);
1289					break;
1290				}
1291			case 'v': {
1292					inc_wmlog_level();
1293					break;
1294				}
1295			case 'D': {
1296					int r;
1297					r = libusb_init(&ctx);
1298					if (r < 0) {
1299						wmlog_msg(0, "failed to initialise libusb");
1300						exit(1);
1301					}
1302					switch_wimax_device();
1303					libusb_exit(ctx);
1304					exit(1);
1305					break;
1306				}
1307			case 'd': {
1308					daemonize = 1;
1309					break;
1310				}
1311			case 'V': {
1312					version();
1313					exit(0);
1314					break;
1315				}
1316			case 'h': {
1317					usage(argv[0]);
1318					exit(0);
1319					break;
1320				}
1321			case '?': {
1322					/* getopt_long already printed an error message. */
1323					usage(argv[0]);
1324					exit(1);
1325					break;
1326				}
1327#ifdef WITH_DBUS
1328			case 7: {
1329					dbus_use = 1;
1330					break;
1331				}
1332#endif /* WITH_DBUS */
1333			case 8: {
1334					xml_file = fopen(optarg, "rb");
1335					if (xml_file == NULL){
1336						wmlog_msg(0, "bad xml file: %s",strerror(errno));
1337						exit(1);
1338					}
1339					break;
1340				}
1341			default: {
1342					exit(1);
1343				}
1344		}
1345	}
1346}
1347
1348static void exit_release_resources(int code)
1349{
1350//Rewrite this part!!!!!!!
1351	if(devh != NULL && wd_status.rf_state == 0){
1352		unsigned char req_data[MAX_PACKET_LEN];
1353		int len;
1354		wmlog_msg(2, "RF OFF.");
1355		len = fill_rf_off_req(req_data);
1356		set_data(req_data, len);
1357		process_events_by_mask(2000, WDS_RF_STATE);
1358	}
1359	if(wd_status.config != NULL && wd_status.config->cert_nv == 1)
1360	{
1361		if(wd_status.config->ca_cert)
1362			remove((const char *)wd_status.config->ca_cert); //Delete this
1363		if(wd_status.config->client_cert)
1364			remove((const char *)wd_status.config->client_cert);
1365	}
1366	if(tap_fd >= 0) {
1367		if_down();
1368		while (wait(NULL) > 0) {}
1369		if_release();
1370		while (wait(NULL) > 0) {}
1371	}
1372	if(ctx != NULL) {
1373		if(req_transfer != NULL) {
1374			libusb_cancel_transfer(req_transfer);
1375			libusb_free_transfer(req_transfer);
1376		}
1377		libusb_set_pollfd_notifiers(ctx, NULL, NULL, NULL);
1378		if(fds != NULL) {
1379			free(fds);
1380		}
1381		if(devh != NULL) {
1382			libusb_release_interface(devh, 0);
1383			if (kernel_driver_active)
1384				libusb_attach_kernel_driver(devh, 0);
1385			libusb_unlock_events(ctx);
1386			libusb_close(devh);
1387		}
1388		libusb_exit(ctx);
1389	}
1390	if (pid_file)
1391	{
1392		unlink(pid_file);
1393		free(pid_file);
1394	}
1395	if(logfile != NULL) {
1396		fclose(logfile);
1397	}
1398	if (dbus_use) {
1399#ifdef WITH_DBUS
1400		DBusMessage *message;
1401		message = dbus_message_new_signal (	"/ua/org/yarx/Daemon",
1402											"ua.org.yarx.Daemon",
1403											"ErrorAndDisconnect");
1404		dbus_message_append_args (	message,
1405									DBUS_TYPE_INVALID);
1406		dbus_connection_send (dbus_connection, message, NULL);
1407		dbus_message_unref (message);
1408#endif /* WITH_DBUS */
1409	}
1410	if(wd_status.config)
1411		gct_config_free(wd_status.config);
1412	exit(code);
1413}
1414
1415static void sighandler_exit(int signum) {
1416	exit_release_resources(0);
1417}
1418
1419static void sighandler_wait_child(int signum) {
1420	int status;
1421	wait3(&status, WNOHANG, NULL);
1422	wmlog_msg(2, "Child exited with status %d", status);
1423}
1424
1425////////////////////////////////////////////////////////////////
1426///////////////////////////////////////////////////////////////
1427//////////////////////////////////////////////////////////////
1428
1429static void dbus_dev_info_send(void) {
1430#ifdef WITH_DBUS
1431	const char *chip = wd_status.chip;
1432	const char *firmware = wd_status.firmware;
1433	char _mac[18];
1434
1435	snprintf(_mac, 18, "%02x:%02x:%02x:%02x:%02x:%02x", wd_status.mac[0], wd_status.mac[1], wd_status.mac[2],
1436							wd_status.mac[3], wd_status.mac[4], wd_status.mac[5]);
1437
1438	const char * mac = _mac;
1439
1440	DBusMessage *message;
1441	message = dbus_message_new_signal (	"/ua/org/yarx/Daemon",
1442										"ua.org.yarx.Daemon",
1443										"SendDeviceInfo");
1444	dbus_message_append_args (	message,
1445								DBUS_TYPE_STRING, &chip,
1446								DBUS_TYPE_STRING, &firmware,
1447								DBUS_TYPE_STRING, &mac,
1448								DBUS_TYPE_INVALID);
1449	dbus_connection_send (dbus_connection, message, NULL);
1450	dbus_message_unref (message);
1451#endif /* WITH_DBUS */
1452}
1453
1454static void dbus_sig_info_send(void) {
1455#ifdef WITH_DBUS
1456	DBusMessage *message;
1457	message = dbus_message_new_signal (	"/ua/org/yarx/Daemon",
1458										"ua.org.yarx.Daemon",
1459										"SendSignalInfo");
1460	dbus_message_append_args (	message,
1461								DBUS_TYPE_INT16, &wd_status.rssi1,
1462								DBUS_TYPE_INT16, &wd_status.rssi2,
1463								DBUS_TYPE_INT16, &wd_status.cinr1,
1464								DBUS_TYPE_INT16, &wd_status.cinr2,
1465								DBUS_TYPE_UINT16, &wd_status.txpwr,
1466								DBUS_TYPE_UINT32, &wd_status.freq,
1467								DBUS_TYPE_INVALID);
1468	dbus_connection_send (dbus_connection, message, NULL);
1469	dbus_message_unref (message);
1470#endif /* WITH_DBUS */
1471}
1472
1473static void dbus_bsid_info_send(void) {
1474#ifdef WITH_DBUS
1475	char _bsid[18];
1476	snprintf(_bsid, 18, "%02x:%02x:%02x:%02x:%02x:%02x", wd_status.bsid[0], wd_status.bsid[1], wd_status.bsid[2],
1477							wd_status.bsid[3], wd_status.bsid[4], wd_status.bsid[5]);
1478
1479	const char *bsid = _bsid;
1480
1481	DBusMessage *message;
1482	message = dbus_message_new_signal (	"/ua/org/yarx/Daemon",
1483										"ua.org.yarx.Daemon",
1484										"SendBsidInfo");
1485	dbus_message_append_args (	message,
1486								DBUS_TYPE_STRING, &bsid,
1487								DBUS_TYPE_INVALID );
1488	dbus_connection_send (dbus_connection, message, NULL);
1489	dbus_message_unref (message);
1490#endif /* WITH_DBUS */
1491}
1492
1493static void dbus_conn_info_send(enum wimax_state state) {
1494#ifdef WITH_DBUS
1495	DBusMessage *message;
1496	message = dbus_message_new_signal (	"/ua/org/yarx/Daemon",
1497										"ua.org.yarx.Daemon",
1498										"SendConnectionInfo");
1499
1500	const char *msg_state = wimax_state_to_name(state);
1501	dbus_message_append_args (	message,
1502								DBUS_TYPE_INT16, &state,
1503								DBUS_TYPE_STRING, &msg_state,
1504								DBUS_TYPE_INVALID );
1505	dbus_connection_send (dbus_connection, message, NULL);
1506
1507	dbus_message_unref (message);
1508#endif /* WITH_DBUS */
1509}
1510
1511
1512static void dbus_percent_info_send(short code, short percent) {
1513#ifdef WITH_DBUS
1514	DBusMessage *message;
1515	message = dbus_message_new_signal (	"/ua/org/yarx/Daemon",
1516										"ua.org.yarx.Daemon",
1517										"SendPercentInfo");
1518	dbus_message_append_args (	message,
1519								DBUS_TYPE_INT16, &code,
1520								DBUS_TYPE_INT16, &percent,
1521								DBUS_TYPE_INVALID );
1522	dbus_connection_send (dbus_connection, message, NULL);
1523
1524	dbus_message_unref (message);
1525#endif /* WITH_DBUS */
1526}
1527////////////////////////////////////////////////////////////////
1528///////////////////////////////////////////////////////////////
1529//////////////////////////////////////////////////////////////
1530
1531static
1532void gct_config_complete()
1533{
1534	struct gct_config *config = wd_status.config;
1535
1536	if(wimax_log_level < config->wimax_verbose_level)
1537		set_wmlog_level(config->wimax_verbose_level);
1538
1539	if (strlen(config->log_file))
1540		logfile = fopen(config->log_file, "a");
1541
1542	if (strlen(config->event_script))
1543		event_script = config->event_script;
1544
1545	wd_status.nspid = config->nspid;
1546
1547	if(config->use_pkm)
1548	{
1549		if(config->ca_cert_null)
1550		{
1551			free(config->ca_cert);
1552			config->ca_cert = NULL;
1553		}
1554
1555		if(config->dev_cert_null)
1556		{
1557			free(config->client_cert);
1558			free(config->private_key);
1559			free(config->private_key_passwd);
1560			config->client_cert = NULL;
1561			config->private_key = NULL;
1562			config->private_key_passwd = NULL;
1563		}
1564
1565		switch(config->eap_type)
1566		{
1567			case -1:
1568				/* Use settings only from config file*/
1569				break;
1570			case 3:
1571				free(config->eap_methods);
1572				free(config->identity);
1573				free(config->password);
1574				free(config->phase1);
1575				free(config->phase2);
1576				config->identity = NULL;
1577				config->password = NULL;
1578				config->identity_len = 0;
1579				config->password_len = 0;
1580				config->eap_methods = calloc(2, sizeof(*config->eap_methods));
1581				config->eap_methods[0].vendor = EAP_VENDOR_IETF;
1582				config->eap_methods[0].method = EAP_TYPE_TLS;
1583				config->phase1 = strdup("include_tls_length=1");
1584				config->phase2 = NULL;
1585				break;
1586			case 4:
1587				free(config->eap_methods);
1588				free(config->phase1);
1589				free(config->phase2);
1590				config->eap_methods = calloc(2, sizeof(*config->eap_methods));
1591				config->eap_methods[0].vendor = EAP_VENDOR_IETF;
1592				config->eap_methods[0].method = EAP_TYPE_TTLS;
1593				config->phase1 = NULL;
1594				config->phase2 = strdup("auth=MD5");
1595				break;
1596			case 5:
1597				free(config->eap_methods);
1598				free(config->phase1);
1599				free(config->phase2);
1600				config->eap_methods = calloc(2, sizeof(*config->eap_methods));
1601				config->eap_methods[0].vendor = EAP_VENDOR_IETF;
1602				config->eap_methods[0].method = EAP_TYPE_TTLS;
1603				config->phase1 = NULL;
1604				config->phase2 = strdup("auth=MSCHAPV2");
1605				break;
1606			case 6:
1607				free(config->eap_methods);
1608				free(config->phase1);
1609				free(config->phase2);
1610				config->eap_methods = calloc(2, sizeof(*config->eap_methods));
1611				config->eap_methods[0].vendor = EAP_VENDOR_IETF;
1612				config->eap_methods[0].method = EAP_TYPE_TTLS;
1613				config->phase1 = NULL;
1614				config->phase2 = strdup("auth=CHAP");
1615				break;
1616			default:
1617				wmlog_msg(0,"E:	EAP Type (%d) not supported yet",
1618					config->eap_type);
1619		}
1620	}
1621}
1622
1623
1624int main(int argc, char **argv)
1625{
1626	struct sigaction sigact;
1627	int r = 1;
1628
1629	set_wmlogger(argv[0], WMLOGGER_FILE, stderr);
1630
1631	wd_status.nspid = 0;
1632
1633	parse_args(argc, argv);
1634
1635	wmlog_msg(2,"Dir  %s",CONF_DIR);
1636
1637#ifdef WITH_DBUS
1638	if (dbus_use) {
1639		dbus_error_init (&dbus_error);
1640		dbus_connection = dbus_bus_get (DBUS_BUS_SESSION, &dbus_error);
1641
1642		if (dbus_connection == NULL) {
1643			wmlog_msg(0, "Failed to connect to the D-BUS: %s\n", dbus_error.message);
1644			exit(1);
1645		}
1646	}
1647#endif /* WITH_DBUS */
1648
1649	if (xml_file)
1650		DL_xml_image();
1651
1652	sigact.sa_handler = sighandler_exit;
1653	sigemptyset(&sigact.sa_mask);
1654	sigact.sa_flags = 0;
1655	sigaction(SIGINT, &sigact, NULL);
1656	sigaction(SIGTERM, &sigact, NULL);
1657	sigaction(SIGQUIT, &sigact, NULL);
1658	sigact.sa_handler = sighandler_wait_child;
1659	sigaction(SIGCHLD, &sigact, NULL);
1660
1661	if (daemonize) {
1662		wmlog_msg(0, "Demon");
1663//		CHECK_NEGATIVE(daemon(0, 0));
1664		if(daemon(0, 0))
1665			exit(1);
1666		if (pid_file) {
1667			FILE *f = fopen(pid_file, "w");
1668			if (f) {
1669				fprintf(f, "%u\n", getpid());
1670				fclose(f);
1671			}
1672		}
1673	}
1674
1675	wd_status.rf_state = 1;  // RF OFF
1676	wd_status.network_status = 0;
1677	wd_status.config = gct_config_read(conf_file); //conf_file
1678	if (!wd_status.config){
1679		wmlog_msg(0, "Bad config file");
1680		exit_release_resources(1);
1681	}
1682
1683	gct_config_complete();
1684
1685	if (logfile != NULL) {
1686		set_wmlogger(argv[0], WMLOGGER_FILE, logfile);
1687	} else if (daemonize || dbus_use) {
1688		set_wmlogger(argv[0], WMLOGGER_SYSLOG, NULL);
1689	} else {
1690		set_wmlogger(argv[0], WMLOGGER_FILE, stderr);
1691	}
1692
1693	r = libusb_init(&ctx);
1694	if (r < 0) {
1695		if (dbus_use) dbus_conn_info_send(WS_DEV_NOT_FOUND);
1696		wmlog_msg(0, "failed to initialise libusb");
1697		exit_release_resources(1);
1698	}
1699
1700	get_wimax_device();
1701
1702	alloc_fds();
1703	libusb_set_pollfd_notifiers(ctx, cb_add_pollfd, cb_remove_pollfd, NULL);
1704
1705	r = init();
1706	if (r < 0) {
1707		if (dbus_use) dbus_conn_info_send(WS_ERR_INIT_DRIVER);
1708		wmlog_msg(0, "init error %d", r);
1709		exit_release_resources(1);
1710	}
1711
1712	if_create();
1713	cb_add_pollfd(tap_fd, POLLIN, NULL);
1714
1715	r = scan_loop();
1716	if (r < 0) {
1717		if (dbus_use) dbus_conn_info_send(WS_ERR_INIT_DRIVER);
1718		wmlog_msg(0, "scan_loop error %d", r);
1719		exit_release_resources(1);
1720	}
1721
1722	exit_release_resources(0);
1723	return 0;
1724}
1725
1726