nfc-relay.c

Go to the documentation of this file.
00001 /*-
00002  * Public platform independent Near Field Communication (NFC) library
00003  * 
00004  * Copyright (C) 2009, 2010, Roel Verdult, Romuald Conty
00005  * 
00006  * This program is free software: you can redistribute it and/or modify it
00007  * under the terms of the GNU Lesser General Public License as published by the
00008  * Free Software Foundation, either version 3 of the License, or (at your
00009  * option) any later version.
00010  * 
00011  * This program is distributed in the hope that it will be useful, but WITHOUT
00012  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00013  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
00014  * more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public License
00017  * along with this program.  If not, see <http://www.gnu.org/licenses/>
00018  */
00019 
00025 #ifdef HAVE_CONFIG_H
00026 #  include "config.h"
00027 #endif /* HAVE_CONFIG_H */
00028 
00029 #include <stdio.h>
00030 #include <stdlib.h>
00031 #include <stdint.h>
00032 #include <string.h>
00033 #include <signal.h>
00034 
00035 #include <nfc/nfc.h>
00036 
00037 #include <nfc/nfc-messages.h>
00038 #include "nfc-utils.h"
00039 
00040 #define MAX_FRAME_LEN 264
00041 #define MAX_DEVICE_COUNT 2
00042 
00043 static byte_t abtReaderRx[MAX_FRAME_LEN];
00044 static byte_t abtReaderRxPar[MAX_FRAME_LEN];
00045 static size_t szReaderRxBits;
00046 static byte_t abtTagRx[MAX_FRAME_LEN];
00047 static byte_t abtTagRxPar[MAX_FRAME_LEN];
00048 static size_t szTagRxBits;
00049 static nfc_device_t *pndReader;
00050 static nfc_device_t *pndTag;
00051 static bool quitting = false;
00052 
00053 void
00054 intr_hdlr (void)
00055 {
00056   printf ("\nQuitting...\n");
00057   quitting = true;
00058   return;
00059 }
00060 
00061 void
00062 print_usage (char *argv[])
00063 {
00064   printf ("Usage: %s [OPTIONS]\n", argv[0]);
00065   printf ("Options:\n");
00066   printf ("\t-h\tHelp. Print this message.\n");
00067   printf ("\t-q\tQuiet mode. Suppress output of READER and EMULATOR data (improves timing).\n");
00068 }
00069 
00070 int
00071 main (int argc, char *argv[])
00072 {
00073   int     arg;
00074   bool    quiet_output = false;
00075   size_t  szFound;
00076   nfc_device_desc_t *pnddDevices;
00077   const char *acLibnfcVersion = nfc_version ();
00078 
00079   // Get commandline options
00080   for (arg = 1; arg < argc; arg++) {
00081     if (0 == strcmp (argv[arg], "-h")) {
00082       print_usage (argv);
00083       return EXIT_SUCCESS;
00084     } else if (0 == strcmp (argv[arg], "-q")) {
00085       INFO ("%s", "Quiet mode.");
00086       quiet_output = true;
00087     } else {
00088       ERR ("%s is not supported option.", argv[arg]);
00089       print_usage (argv);
00090       return EXIT_FAILURE;
00091     }
00092   }
00093 
00094   // Display libnfc version
00095   printf ("%s use libnfc %s\n", argv[0], acLibnfcVersion);
00096 
00097 #ifdef WIN32
00098   signal (SIGINT, (void (__cdecl *) (int)) intr_hdlr);
00099 #else
00100   signal (SIGINT, (void (*)()) intr_hdlr);
00101 #endif
00102 
00103   // Allocate memory to put the result of available devices listing
00104   if (!(pnddDevices = malloc (MAX_DEVICE_COUNT * sizeof (*pnddDevices)))) {
00105     fprintf (stderr, "malloc() failed\n");
00106     return EXIT_FAILURE;
00107   }
00108   // List available devices
00109   nfc_list_devices (pnddDevices, MAX_DEVICE_COUNT, &szFound);
00110 
00111   if (szFound < 2) {
00112     ERR ("%zd device found but two connected devices are needed to relay NFC.", szFound);
00113     return EXIT_FAILURE;
00114   }
00115   // Try to open the NFC emulator device
00116   pndTag = nfc_connect (&(pnddDevices[0]));
00117   if (pndTag == NULL) {
00118     printf ("Error connecting NFC emulator device\n");
00119     return EXIT_FAILURE;
00120   }
00121 
00122   printf ("Hint: tag <---> emulator (relay) <---> reader (relay) <---> original reader\n\n");
00123 
00124   printf ("Connected to the NFC emulator device: %s\n", pndTag->acName);
00125   printf ("[+] Try to break out the auto-emulation, this requires a second reader!\n");
00126   printf ("[+] To do this, please send any command after the anti-collision\n");
00127   printf ("[+] For example, send a RATS command or use the \"nfc-anticol\" tool\n");
00128   if (!nfc_target_init (pndTag, abtReaderRx, &szReaderRxBits)) {
00129     ERR ("%s", "Initialization of NFC emulator failed");
00130     nfc_disconnect (pndTag);
00131     return EXIT_FAILURE;
00132   }
00133   printf ("%s", "Configuring emulator settings...");
00134   if (!nfc_configure (pndTag, NDO_HANDLE_CRC, false) ||
00135       !nfc_configure (pndTag, NDO_HANDLE_PARITY, false) || !nfc_configure (pndTag, NDO_ACCEPT_INVALID_FRAMES, true)) {
00136     nfc_perror (pndTag, "nfc_configure");
00137     exit (EXIT_FAILURE);
00138   }
00139   printf ("%s", "Done, emulated tag is initialized");
00140 
00141   // Try to open the NFC reader
00142   pndReader = nfc_connect (&(pnddDevices[1]));
00143 
00144   printf ("Connected to the NFC reader device: %s", pndReader->acName);
00145   printf ("%s", "Configuring NFC reader settings...");
00146   nfc_initiator_init (pndReader);
00147   if (!nfc_configure (pndReader, NDO_HANDLE_CRC, false) ||
00148       !nfc_configure (pndReader, NDO_HANDLE_PARITY, false) ||
00149       !nfc_configure (pndReader, NDO_ACCEPT_INVALID_FRAMES, true)) {
00150     nfc_perror (pndReader, "nfc_configure");
00151     exit (EXIT_FAILURE);
00152   }
00153   printf ("%s", "Done, relaying frames now!");
00154 
00155   while (!quitting) {
00156     // Test if we received a frame from the reader
00157     if (nfc_target_receive_bits (pndTag, abtReaderRx, &szReaderRxBits, abtReaderRxPar)) {
00158       // Drop down the field before sending a REQA command and start a new session
00159       if (szReaderRxBits == 7 && abtReaderRx[0] == 0x26) {
00160         // Drop down field for a very short time (original tag will reboot)
00161         if (!nfc_configure (pndReader, NDO_ACTIVATE_FIELD, false)) {
00162           nfc_perror (pndReader, "nfc_configure");
00163           exit (EXIT_FAILURE);
00164         }
00165         if (!quiet_output)
00166           printf ("\n");
00167         if (!nfc_configure (pndReader, NDO_ACTIVATE_FIELD, true)) {
00168           nfc_perror (pndReader, "nfc_configure");
00169           exit (EXIT_FAILURE);
00170         }
00171       }
00172       // Print the reader frame to the screen
00173       if (!quiet_output) {
00174         printf ("R: ");
00175         print_hex_par (abtReaderRx, szReaderRxBits, abtReaderRxPar);
00176       }
00177       // Forward the frame to the original tag
00178       if (nfc_initiator_transceive_bits
00179           (pndReader, abtReaderRx, szReaderRxBits, abtReaderRxPar, abtTagRx, &szTagRxBits, abtTagRxPar)) {
00180         // Redirect the answer back to the reader
00181         if (!nfc_target_send_bits (pndTag, abtTagRx, szTagRxBits, abtTagRxPar)) {
00182           nfc_perror (pndTag, "nfc_target_send_bits");
00183           exit (EXIT_FAILURE);
00184         }
00185         // Print the tag frame to the screen
00186         if (!quiet_output) {
00187           printf ("T: ");
00188           print_hex_par (abtTagRx, szTagRxBits, abtTagRxPar);
00189         }
00190       }
00191     }
00192   }
00193 
00194   nfc_disconnect (pndTag);
00195   nfc_disconnect (pndReader);
00196   exit (EXIT_SUCCESS);
00197 }