4 * Copyright (C) 2008 Dave Hansen <dave@sr71.net>
6 * This software may be redistributed and/or modified under the terms of
7 * the GNU General Public License ("GPL") version 2 as published by the
8 * Free Software Foundation.
17 #include <sys/types.h>
22 #include "eyefi-config.h"
25 #define debug_printf(level, args...) do { \
26 if ((level) <= debug_level) \
27 fprintf(stderr, ## args); \
30 #define O_DIRECT 00040000 /* direct disk access hint */
39 #define PATHNAME_MAX 4096
40 char eyefi_mount[PATHNAME_MAX]; // PATH_MAX anyone?
41 static char *eyefi_file_name(enum eyefi_file file)
44 case REQC: return "reqc";
45 case REQM: return "reqm";
46 case RSPC: return "rspc";
47 case RSPM: return "rspm";
53 static char *eyefi_file_on(enum eyefi_file file, char *mnt)
55 char *filename = eyefi_file_name(file);
56 char *full = malloc(PATHNAME_MAX);
58 sprintf(&full[0], "%s/EyeFi/%s", mnt, filename);
59 debug_printf(4, "eyefile nr: %d on '%s' is: '%s'\n", file, mnt, &full[0]);
65 #define EYEFI_BUF_SIZE 16384
66 char unaligned_buf[BUFSZ*2];
70 * Just a few functions so that I can't easily forget about
75 } __attribute__((packed));
76 typedef struct __be32 be32;
79 * These two obviously need to get fixed for
80 * big endian machines.
82 u32 be32_to_u32(be32 src)
84 return swap_bytes(src.val);
86 be32 u32_to_be32(u32 src)
89 ret.val = swap_bytes(src);
93 void dumpbuf(const char *buffer, int bytesToWrite)
96 static char linebuf[500];
98 for (i=0; i < bytesToWrite; i += 16) {
99 char *tmpbuf = &linebuf[0];
100 unsigned long sum = 0;
102 #define lprintf(args...) do { \
103 tmpbuf += sprintf(tmpbuf, ## args);\
106 lprintf("[%03d]: ", i);
107 for (j=0; j < 16; j++) {
108 u8 c = ((unsigned char *)buffer)[i+j];
109 lprintf("%02x ", (unsigned int)c);
113 for (j=0; j < 16; j++) {
114 u8 c = ((unsigned char *)buffer)[i+j];
115 if (c >= 'a' && c <= 'z')
117 else if (c >= 'A' && c <= 'Z')
119 else if (c >= '0' && c <= '9')
121 else if (c >= 0x20 && c <= 127)
129 printf("%s", linebuf);
135 struct card_seq_num {
137 } __attribute__((packed));
139 void read_from(enum eyefi_file);
140 void write_to(enum eyefi_file, void *, int);
141 struct card_seq_num read_seq_from(enum eyefi_file file)
143 struct card_seq_num *ret;
150 * For O_DIRECT writes to files, we need
151 * to be 512 byte aligned on Linux, I think.
152 * So, just align this to something big
153 * and be done with it. FIXME :)
157 unsigned long addr = (unsigned long)&unaligned_buf[BUFSZ];
160 debug_printf(4, "buf: %p\n", buf);
161 debug_printf(4, "unaligned: %p\n", &unaligned_buf[0]);
164 struct card_seq_num seq;
167 * The real manager does this so we might
170 void zero_card_files(void)
172 //write_to(REQM, buf, BUFSZ);
173 write_to(REQC, buf, BUFSZ);
174 write_to(RSPM, buf, BUFSZ);
175 write_to(RSPC, buf, BUFSZ);
185 if ((c >= 'A') && (c <= 'Z'))
193 if ((c >= '0') && (c <= '9'))
195 else if ((c >= 'a') && (c <= 'z'))
196 return (c - 'a') + 10;
197 debug_printf(5, "non-hex character: '%c'/'%c'\n", c, lc);
203 if ((o >= '0') && (o <= '7'))
208 int octal_esc_to_chr(char *input) {
211 int len = strlen(input);
213 //intf("%s('%s')\n", __func__, input);
214 if (input[0] != '\\')
219 for (i=1; i < len ; i++) {
222 int tmp = atoo(input[i]);
223 //intf("tmp: %d\n", tmp);
232 char *replace_escapes(char *str)
236 debug_printf(4, "%s(%s)\n", __func__, str);
237 for (i=0; i < strlen(str); i++) {
238 int esc = octal_esc_to_chr(&str[i]);
244 str[output++] = str[i];
247 debug_printf(4, "replaced escapes in: '%s' bytes of output: %d\n", str, output);
251 #define LINEBUFSZ 1024
252 char *locate_eyefi_mount(void)
254 char line[LINEBUFSZ];
255 FILE *mounts = fopen("/proc/mounts", "r");
264 if (strlen(eyefi_mount))
265 return &eyefi_mount[0];
267 while (fgets(&line[0], 1023, mounts)) {
269 read = sscanf(&line[0], "%s %s %s %s %d %d",
270 &dev[0], &mnt[0], &fs[0], &opt[0],
272 // only look at fat filesystems:
273 if (strcmp(fs, "msdos") && strcmp(fs, "vfat")) {
274 debug_printf(2, "fs at '%s' is not fat, skipping...\n", mnt);
277 // Linux's /proc/mounts has spaces like this \040
278 replace_escapes(&mnt[0]);
279 char *file = eyefi_file_on(REQM, &mnt[0]);
280 debug_printf(2, "looking for EyeFi file here: '%s'\n", file);
284 statret = stat(file, &statbuf);
287 debug_printf(2, "fs at: %s is not an Eye-Fi card, skipping...\n",
291 strcpy(&eyefi_mount[0], &mnt[0]);
292 debug_printf(1, "located EyeFi card at: '%s'\n", eyefi_mount);
296 if (strlen(eyefi_mount))
297 return &eyefi_mount[0];
307 debug_printf(2, "Initializing card...\n");
308 mnt = locate_eyefi_mount();
310 debug_printf(1, "unable to locate Eye-Fi card\n");
312 debug_printf(0, "please run with '-d5' option and report the output\n");
314 debug_printf(0, "----------------------------------------------\n");
315 debug_printf(0, "Debug information:\n");
316 system("cat /proc/mounts >&2");
323 seq = read_seq_from(RSPC);
326 debug_printf(2, "Done initializing card...\n");
329 static char *eyefi_file(enum eyefi_file file)
332 return eyefi_file_on(file, &eyefi_mount[0]);
335 void open_error(char *file)
337 fprintf(stderr, "unable to open '%s'\n", file);
338 fprintf(stderr, "Is the Eye-Fi card inserted and mounted at: %s ?\n", eyefi_mount);
339 fprintf(stderr, "Do you have write permissions to it?\n");
340 fprintf(stderr, "debug information:\n");
342 system("cat /proc/mounts >&2");
348 void read_from(enum eyefi_file __file)
355 char *file = eyefi_file(__file);
359 fd = open(file, O_RDONLY);
362 retcntl = fcntl(fd, F_SETFL, O_DIRECT);
367 ret = read(fd, buf, BUFSZ);
374 debug_printf(4, "read '%s': bytes: %d fcntl: %d\n", file, ret, retcntl);
375 for (i=0; i < BUFSZ; i++) {
376 c = ((char *)buf)[i];
383 // printf(" zeros: %d", zeros);
389 void write_to(enum eyefi_file __file, void *stuff, int len)
396 file = eyefi_file(__file);
400 if (debug_level > 3) {
401 debug_printf(3, "%s('%s', ..., %d)\n", __func__, file, len);
404 memset(buf, 0, BUFSZ);
405 memcpy(buf, stuff, len);
406 fd = open(file, O_RDWR|O_DIRECT|O_CREAT, 0600);
407 //ret = lseek(fd, 0, SEEK_SET);
412 ret = write(fd, buf, BUFSZ);
415 debug_printf(3, "wrote %d bytes to '%s' (string was %d bytes)\n", ret, file, len);
417 fprintf(stderr, "error writing to '%s': ", file);
425 * Most of the eyefi strings are pascal-style with
426 * a length byte preceeding content. (Did pascal
427 * have just a byte for length or more??)
429 struct pascal_string {
432 } __attribute__((packed));
434 void print_pascal_string(struct pascal_string *str)
437 for (i = 0; i < str->length; i++)
438 printf("%c", str->value[i]);
442 * The 'o' command has several sub-commands:
444 enum card_info_subcommand {
449 UNKNOWN1 = 5, // Chris says these are
450 UNKNOWN2 = 6, // checksums
454 struct card_info_req {
457 } __attribute__((packed));
459 struct card_info_rsp_key {
460 struct pascal_string key;
463 struct card_firmware_info {
464 struct pascal_string info;
471 } __attribute__((packed));
473 struct card_info_api_url {
474 struct pascal_string key;
477 struct card_info_log_len {
480 } __attribute__((packed));
482 #define write_struct(file, s) write_to((file), s, sizeof(*(s)))
484 void print_mac(struct mac_address *mac)
487 for (i=0; i < MAC_BYTES-1; i++) {
488 printf("%02x:", mac->mac[i]);
490 printf("%02x\n", mac->mac[i]);
495 //u32 tmpseq = be32_to_u32(seq.seq);
496 //seq.seq = u32_to_be32(tmpseq+1);
498 write_struct(REQC, &seq);
501 u32 current_seq(void)
506 int wait_for_response(void)
509 debug_printf(3, "waiting for response...\n");
511 for (i = 0; i < 50; i++) {
512 struct card_seq_num cardseq = read_seq_from(RSPC);
513 u32 rsp = cardseq.seq;
514 debug_printf(3, "read rsp code: %lx, looking for: %lx raw: %lx\n", rsp, current_seq(),
516 if (rsp == current_seq())
521 debug_printf(1, "never saw card seq response\n");
524 debug_printf(3, "got good seq, reading RSPM...\n");
526 debug_printf(3, "done reading RSPM\n");
529 struct byte_response {
542 char essid[ESSID_LEN];
543 signed char strength;
545 } __attribute__((packed));
547 struct scanned_net_list {
549 struct scanned_net nets[100];
550 } __attribute__((packed));
552 struct configured_net {
553 char essid[ESSID_LEN];
554 } __attribute__((packed));
556 struct configured_net_list {
558 struct configured_net nets[100];
559 } __attribute__((packed));
561 char *net_test_states[] = {
564 "verifying network key",
566 "testing connection to Eye-Fi server",
570 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
572 char *net_test_state_name(u8 state)
574 int size = ARRAY_SIZE(net_test_states);
577 return net_test_states[state];
580 char *net_types[] = {
588 char *net_type_name(u8 type)
590 int size = ARRAY_SIZE(net_types);
593 return net_types[type];
596 #define WPA_KEY_BYTES 32
598 u8 key[WPA_KEY_BYTES];
599 } __attribute((packed));
601 #define WEP_KEY_BYTES 32
603 u8 key[WEP_KEY_BYTES];
604 } __attribute((packed));
612 } __attribute((packed));
618 char essid[ESSID_LEN];
619 struct network_key key;
620 } __attribute((packed));
623 * Take a string like "0ab1" and make it
624 * a series of bytes: { 0x0a, 0xb1 }
626 * @len is the strlen() of the ascii
628 * Destroys the original string.
630 char *convert_ascii_to_hex(char *ascii, int len)
634 fprintf(stderr, "%s() must be even number of bytes: %d\n",
638 for (i=0; i < len; i+=2) {
639 int high = atoh(ascii[i]);
640 int low = atoh(ascii[i+1]);
641 u8 byte = (high<<4 | low);
642 if (high < 0 || low < 0)
644 debug_printf(6, "high: %02x low: %02x, both: %02x\n", high, low, byte);
647 for (i=len/2; i < len; i++)
652 #define PASSPHRASE_PROG "wpa_passphrase"
654 struct wpa_key *make_wpa_key(char *essid, char *pass)
656 struct wpa_key *key = malloc(sizeof(*key));
658 if (strlen(pass) == WPA_KEY_BYTES*2) {
660 debug_printf(2, "Interpreting password as hex WPA key\n");
661 hex_pass = convert_ascii_to_hex(pass, WPA_KEY_BYTES*2);
664 memcpy(&key->key[0], pass, WPA_KEY_BYTES);
666 debug_printf(2, "Interpreting password as ASCII WPA key\n");
667 pbkdf2_sha1(pass, essid, strlen(essid), 4096,
668 &key->key[0], WPA_KEY_BYTES);
673 int card_info_cmd(enum card_info_subcommand cmd)
675 struct card_info_req cir;
677 cir.subcommand = cmd;
679 write_struct(REQM, &cir);
680 return wait_for_response();
683 u32 fetch_log_length(void)
685 card_info_cmd(LOG_LEN);
686 struct card_info_log_len *loglen = buf;
687 return be32_to_u32(loglen->val);
690 void print_log_len(void)
692 u32 len = fetch_log_length();
693 printf("log len: %08lx\n", len);
696 void print_card_mac(void)
698 debug_printf(2, "%s()\n", __func__);
699 card_info_cmd(MAC_ADDRESS);
700 struct mac_address *mac = buf;
701 assert(mac->length == MAC_BYTES);
702 printf("card mac address: ");
706 void print_card_firmware_info(void)
708 debug_printf(2, "%s()\n", __func__);
709 card_info_cmd(FIRMWARE_INFO);
710 struct card_firmware_info *info = buf;
711 printf("card firmware (len: %d): '", info->info.length);
712 print_pascal_string(&info->info);
716 void print_card_key(void)
718 debug_printf(2, "%s()\n", __func__);
719 card_info_cmd(CARD_KEY);
720 struct card_info_rsp_key *foo = buf;
721 printf("card key (len: %d): '", foo->key.length);
722 print_pascal_string(&foo->key);
726 struct noarg_request {
730 int issue_noarg_command(u8 cmd)
732 struct noarg_request req;
734 write_struct(REQM, &req);
735 return wait_for_response();
738 void scan_print_nets(void)
742 debug_printf(2, "%s()\n", __func__);
743 issue_noarg_command('g');
744 struct scanned_net_list *scanned = buf;
745 if (scanned->nr == 0) {
746 printf("unable to detect any wireless networks\n");
749 printf("Scanned wireless networks:\n");
750 for (i=0; i < scanned->nr; i++) {
751 struct scanned_net *net = &scanned->nets[i];
752 printf("'%s' type(%d): %s, strength: %d\n", net->essid,
754 net_type_name(net->type),
759 void print_configured_nets(void)
762 struct configured_net_list *configured;
764 debug_printf(2, "%s()\n", __func__);
765 issue_noarg_command('l');
767 if (configured->nr == 0) {
768 printf("No wireless networks configured on card\n");
771 printf("configured wireless networks:\n");
772 for (i=0; i < configured->nr; i++) {
773 struct configured_net *net = &configured->nets[i];
774 printf("'%s'\n", net->essid);
778 void reboot_card(void)
780 debug_printf(2, "%s()\n", __func__);
781 issue_noarg_command('b');
784 void copy_wep_key(struct wep_key *dst, struct wep_key *src)
786 memcpy(&dst->key, &src->key, sizeof(*dst));
789 void copy_wpa_key(struct wpa_key *dst, struct wpa_key *src)
791 memcpy(&dst->key, &src->key, sizeof(*dst));
794 int network_action(char cmd, char *essid, char *wpa_ascii)
796 struct net_request nr;
797 memset(&nr, 0, sizeof(nr));
800 strcpy(&nr.essid[0], essid);
801 nr.essid_len = strlen(essid);
802 struct wpa_key *wpakey;
804 wpakey = make_wpa_key(essid, wpa_ascii);
805 nr.key.len = sizeof(*wpakey);
806 copy_wpa_key(&nr.key.wpa, wpakey);
808 write_struct(REQM, &nr);
809 return wait_for_response();
812 void add_network(char *essid, char *wpa_ascii)
814 debug_printf(2, "%s()\n", __func__);
815 network_action('a', essid, wpa_ascii);
818 void remove_network(char *essid)
820 debug_printf(2, "%s()\n", __func__);
821 network_action('d', essid, NULL);
824 int try_connection_to(char *essid, char *wpa_ascii)
829 char *type = net_type_name(WPA);
831 type = net_type_name(UNSECURED);
832 printf("trying to connect to %s network: '%s'", type, essid);
834 printf(" with passphrase: '%s'", wpa_ascii);
838 network_action('t', essid, wpa_ascii);
842 for (i=0; i < 200; i++) {
843 struct byte_response *r;
844 issue_noarg_command('s');
847 char *state = net_test_state_name(rsp);
848 if (rsp == last_rsp) {
853 printf("\nTesting connecion to '%s' (%d): %s", essid, rsp, state);
857 if (!strcmp("success", state)) {
861 if (!strcmp("not scanning", state))
863 if (!strcmp("unknown", state))
868 printf("Succeeded connecting to: '%s'\n", essid);
870 printf("Unable to connect to: '%s' (final state: %d/'%s')\n", essid,
871 rsp, net_test_state_name(rsp));
876 struct fetch_log_cmd {
879 } __attribute__((packed));
882 * When you ask for the log at offset 0x0, you
883 * get back 8 bytes of offsets into the rest of
886 struct first_log_response {
889 u8 data[EYEFI_BUF_SIZE-8];
890 } __attribute__((packed));
892 struct rest_log_response {
893 u8 data[EYEFI_BUF_SIZE];
894 } __attribute__((packed));
896 unsigned char *get_log_at_offset(u32 offset)
899 struct fetch_log_cmd cmd;
901 cmd.offset = u32_to_be32(offset);
903 debug_printf(2, "getting log at offset: %08lx\n", offset);
904 write_struct(REQM, &cmd);
905 ret = wait_for_response();
917 u32 log_size = fetch_log_length();
918 char *resbuf = malloc(log_size);
920 int nr_bufs_per_log = log_size/EYEFI_BUF_SIZE;
921 for (i = 0; i < log_size/EYEFI_BUF_SIZE; i++) {
922 debug_printf(1, "fetching EyeFi card log part %d/%d...",
923 i+1, nr_bufs_per_log);
925 get_log_at_offset(EYEFI_BUF_SIZE*i);
926 debug_printf(1, "done\n");
930 struct first_log_response *log = buf;
931 log_end = be32_to_u32(log->log_end);
932 log_start = be32_to_u32(log->log_start);
933 debug_printf(2, "log end: 0x%04lx\n", log_end);
934 debug_printf(2, "log start: 0x%04lx\n", log_start);
935 log_data = &log->data[0];
936 log_size = ARRAY_SIZE(log->data);
938 struct rest_log_response *log = buf;
939 log_data = &log->data[0];
940 log_size = ARRAY_SIZE(log->data);
942 debug_printf(3, "writing %ld bytes to resbuf[%d]\n",
943 log_size, total_bytes);
944 memcpy(&resbuf[total_bytes], log_data, log_size);
945 total_bytes += log_size;
947 // The last byte *should* be a null, and the
948 // official software does not print it.
949 for (i = 0; i < total_bytes-1; i++) {
950 int offset = (log_start+i)%total_bytes;
951 char c = resbuf[offset];
952 // the official software converts UNIX to DOS-style
953 // line breaks, so we'll do the same
959 // just some simple sanity checking to make sure what
960 // we are fetching looks valid
961 int null_bytes_left = 20;
962 if (resbuf[log_end] != 0) {
963 debug_printf(2, "error: unexpected last byte (%ld/0x%lx) of log: %02x\n",
964 log_end, log_end, resbuf[log_end]);
965 for (i=0; i<log_size; i++) {
968 if (null_bytes_left <= 0)
971 debug_printf(2, "null byte %d\n", i);
981 printf(" eyefitest [OPTIONS]\n");
982 printf(" -a ESSID add network (implies test unless --force)\n");
983 printf(" -t ESSID test network\n");
984 printf(" -p KEY set WPA key for add/test\n");
985 printf(" -r ESSID remove network\n");
986 printf(" -s scan for networks\n");
987 printf(" -c list configured networks\n");
988 printf(" -b reboot card\n");
989 printf(" -f print information about card firmware\n");
990 printf(" -d level set debugging level (default: 1)\n");
991 printf(" -k print card unique key\n");
992 printf(" -l dump card log\n");
993 printf(" -m print card mac\n");
997 int main(int argc, char **argv)
1002 debug_printf(3, "%s starting...\n", argv[0]);
1004 //static int passed_wep = 0;
1005 //static int passed_wpa = 0;
1006 static int force = 0;
1007 static struct option long_options[] = {
1008 //{"wep", 'x', &passed_wep, 1},
1009 //{"wpa", 'y', &passed_wpa, 1},
1010 {"force", 0, &force, 1},
1011 {"help", 'h', NULL, 1},
1017 char *passwd = NULL;
1018 char network_action = 0;
1019 debug_printf(3, "about to parse arguments\n");
1020 while ((c = getopt_long_only(argc, argv, "a:bcd:kflmp:r:st:",
1021 &long_options[0], &option_index)) != -1) {
1022 debug_printf(3, "argument: '%c' %d optarg: '%s'\n", c, c, optarg);
1025 // was a long argument
1037 print_configured_nets();
1040 debug_level = atoi(optarg);
1041 fprintf(stderr, "set debug level to: %d\n", debug_level);
1044 print_card_firmware_info();
1067 debug_printf(3, "after arguments essid: '%s' passwd: '%s'\n", essid, passwd);
1068 if (network_action && essid) {
1071 switch (network_action) {
1073 ret = try_connection_to(essid, passwd);
1077 ret = try_connection_to(essid, passwd);
1079 debug_printf(1, "forced: skipping network test\n");
1082 printf("Error connecting to network '%s', not adding.\n", essid);
1083 printf("use --force to override\n");
1086 add_network(essid, passwd);
1089 remove_network(essid);