libnfc  1.4.2
nfc-relay.c
Go to the documentation of this file.
00001 /*-
00002  * Public platform independent Near Field Communication (NFC) library examples
00003  * 
00004  * Copyright (C) 2009, Roel Verdult
00005  * Copyright (C) 2010, Romuald Conty
00006  * 
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted provided that the following conditions are met:
00009  *  1) Redistributions of source code must retain the above copyright notice,
00010  *  this list of conditions and the following disclaimer. 
00011  *  2 )Redistributions in binary form must reproduce the above copyright
00012  *  notice, this list of conditions and the following disclaimer in the
00013  *  documentation and/or other materials provided with the distribution.
00014  *
00015  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00016  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00017  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00018  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
00019  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00020  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00021  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00022  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00023  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00024  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00025  * POSSIBILITY OF SUCH DAMAGE.
00026  * 
00027  * Note that this license only applies on the examples, NFC library itself is under LGPL
00028  *
00029  */
00030 
00036 #ifdef HAVE_CONFIG_H
00037 #  include "config.h"
00038 #endif /* HAVE_CONFIG_H */
00039 
00040 #include <stdio.h>
00041 #include <stdlib.h>
00042 #include <stdint.h>
00043 #include <string.h>
00044 #include <signal.h>
00045 
00046 #include <nfc/nfc.h>
00047 
00048 #include <nfc/nfc-messages.h>
00049 #include "nfc-utils.h"
00050 
00051 #define MAX_FRAME_LEN 264
00052 #define MAX_DEVICE_COUNT 2
00053 
00054 static byte_t abtReaderRx[MAX_FRAME_LEN];
00055 static byte_t abtReaderRxPar[MAX_FRAME_LEN];
00056 static size_t szReaderRxBits;
00057 static byte_t abtTagRx[MAX_FRAME_LEN];
00058 static byte_t abtTagRxPar[MAX_FRAME_LEN];
00059 static size_t szTagRxBits;
00060 static nfc_device_t *pndReader;
00061 static nfc_device_t *pndTag;
00062 static bool quitting = false;
00063 
00064 void
00065 intr_hdlr (void)
00066 {
00067   printf ("\nQuitting...\n");
00068   quitting = true;
00069   return;
00070 }
00071 
00072 void
00073 print_usage (char *argv[])
00074 {
00075   printf ("Usage: %s [OPTIONS]\n", argv[0]);
00076   printf ("Options:\n");
00077   printf ("\t-h\tHelp. Print this message.\n");
00078   printf ("\t-q\tQuiet mode. Suppress output of READER and EMULATOR data (improves timing).\n");
00079 }
00080 
00081 int
00082 main (int argc, char *argv[])
00083 {
00084   int     arg;
00085   bool    quiet_output = false;
00086   size_t  szFound;
00087   nfc_device_desc_t *pnddDevices;
00088   const char *acLibnfcVersion = nfc_version ();
00089 
00090   // Get commandline options
00091   for (arg = 1; arg < argc; arg++) {
00092     if (0 == strcmp (argv[arg], "-h")) {
00093       print_usage (argv);
00094       return EXIT_SUCCESS;
00095     } else if (0 == strcmp (argv[arg], "-q")) {
00096       quiet_output = true;
00097     } else {
00098       ERR ("%s is not supported option.", argv[arg]);
00099       print_usage (argv);
00100       return EXIT_FAILURE;
00101     }
00102   }
00103 
00104   // Display libnfc version
00105   printf ("%s use libnfc %s\n", argv[0], acLibnfcVersion);
00106 
00107 #ifdef WIN32
00108   signal (SIGINT, (void (__cdecl *) (int)) intr_hdlr);
00109 #else
00110   signal (SIGINT, (void (*)()) intr_hdlr);
00111 #endif
00112 
00113   // Allocate memory to put the result of available devices listing
00114   if (!(pnddDevices = malloc (MAX_DEVICE_COUNT * sizeof (*pnddDevices)))) {
00115     fprintf (stderr, "malloc() failed\n");
00116     return EXIT_FAILURE;
00117   }
00118   // List available devices
00119   nfc_list_devices (pnddDevices, MAX_DEVICE_COUNT, &szFound);
00120 
00121   if (szFound < 2) {
00122     ERR ("%zd device found but two connected devices are needed to relay NFC.", szFound);
00123     return EXIT_FAILURE;
00124   }
00125   // Try to open the NFC emulator device
00126   pndTag = nfc_connect (&(pnddDevices[0]));
00127   if (pndTag == NULL) {
00128     printf ("Error connecting NFC emulator device\n");
00129     return EXIT_FAILURE;
00130   }
00131 
00132   printf ("Hint: tag <---> initiator (relay) <---> target (relay) <---> original reader\n\n");
00133 
00134   printf ("Connected to the NFC emulator device: %s\n", pndTag->acName);
00135   printf ("[+] Try to break out the auto-emulation, this requires a second reader!\n");
00136   printf ("[+] To do this, please send any command after the anti-collision\n");
00137   printf ("[+] For example, send a RATS command or use the \"nfc-anticol\" tool\n");
00138 
00139   nfc_target_t nt = {
00140     .nm.nmt = NMT_ISO14443A,
00141     .nm.nbr = NBR_UNDEFINED,
00142     .nti.nai.abtAtqa = { 0x04, 0x00 },
00143     .nti.nai.abtUid = { 0xde, 0xad, 0xbe, 0xef },
00144     .nti.nai.btSak = 0x20,
00145     .nti.nai.szUidLen = 4,
00146     .nti.nai.szAtsLen = 0,
00147   };
00148 
00149   if (!nfc_target_init (pndTag, &nt, abtReaderRx, &szReaderRxBits)) {
00150     ERR ("%s", "Initialization of NFC emulator failed");
00151     nfc_disconnect (pndTag);
00152     return EXIT_FAILURE;
00153   }
00154   printf ("%s", "Configuring emulator settings...");
00155   if (!nfc_configure (pndTag, NDO_HANDLE_CRC, false) ||
00156       !nfc_configure (pndTag, NDO_HANDLE_PARITY, false) || !nfc_configure (pndTag, NDO_ACCEPT_INVALID_FRAMES, true)) {
00157     nfc_perror (pndTag, "nfc_configure");
00158     exit (EXIT_FAILURE);
00159   }
00160   printf ("%s", "Done, emulated tag is initialized");
00161 
00162   // Try to open the NFC reader
00163   pndReader = nfc_connect (&(pnddDevices[1]));
00164 
00165   printf ("Connected to the NFC reader device: %s", pndReader->acName);
00166   printf ("%s", "Configuring NFC reader settings...");
00167   nfc_initiator_init (pndReader);
00168   if (!nfc_configure (pndReader, NDO_HANDLE_CRC, false) ||
00169       !nfc_configure (pndReader, NDO_HANDLE_PARITY, false) ||
00170       !nfc_configure (pndReader, NDO_ACCEPT_INVALID_FRAMES, true)) {
00171     nfc_perror (pndReader, "nfc_configure");
00172     exit (EXIT_FAILURE);
00173   }
00174   printf ("%s", "Done, relaying frames now!");
00175 
00176   while (!quitting) {
00177     // Test if we received a frame from the reader
00178     if (nfc_target_receive_bits (pndTag, abtReaderRx, &szReaderRxBits, abtReaderRxPar)) {
00179       // Drop down the field before sending a REQA command and start a new session
00180       if (szReaderRxBits == 7 && abtReaderRx[0] == 0x26) {
00181         // Drop down field for a very short time (original tag will reboot)
00182         if (!nfc_configure (pndReader, NDO_ACTIVATE_FIELD, false)) {
00183           nfc_perror (pndReader, "nfc_configure");
00184           exit (EXIT_FAILURE);
00185         }
00186         if (!quiet_output)
00187           printf ("\n");
00188         if (!nfc_configure (pndReader, NDO_ACTIVATE_FIELD, true)) {
00189           nfc_perror (pndReader, "nfc_configure");
00190           exit (EXIT_FAILURE);
00191         }
00192       }
00193       // Print the reader frame to the screen
00194       if (!quiet_output) {
00195         printf ("R: ");
00196         print_hex_par (abtReaderRx, szReaderRxBits, abtReaderRxPar);
00197       }
00198       // Forward the frame to the original tag
00199       if (nfc_initiator_transceive_bits
00200           (pndReader, abtReaderRx, szReaderRxBits, abtReaderRxPar, abtTagRx, &szTagRxBits, abtTagRxPar)) {
00201         // Redirect the answer back to the reader
00202         if (!nfc_target_send_bits (pndTag, abtTagRx, szTagRxBits, abtTagRxPar)) {
00203           nfc_perror (pndTag, "nfc_target_send_bits");
00204           exit (EXIT_FAILURE);
00205         }
00206         // Print the tag frame to the screen
00207         if (!quiet_output) {
00208           printf ("T: ");
00209           print_hex_par (abtTagRx, szTagRxBits, abtTagRxPar);
00210         }
00211       }
00212     }
00213   }
00214 
00215   nfc_disconnect (pndTag);
00216   nfc_disconnect (pndReader);
00217   exit (EXIT_SUCCESS);
00218 }