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 "bitutils.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 intr_hdlr(void)
00054 {
00055   printf("\nQuitting...\n");
00056   quitting=true;
00057   return;
00058 }
00059 
00060 void print_usage(char* argv[])
00061 {
00062   printf("Usage: %s [OPTIONS]\n", argv[0]);
00063   printf("Options:\n");
00064   printf("\t-h\tHelp. Print this message.\n");
00065   printf("\t-q\tQuiet mode. Suppress output of READER and EMULATOR data (improves timing).\n");
00066 }
00067 
00068 int main(int argc,char* argv[])
00069 {
00070   int arg;
00071   bool quiet_output = false;
00072   size_t szFound;
00073   nfc_device_desc_t *pnddDevices;
00074   const char* acLibnfcVersion = nfc_version();
00075 
00076   // Get commandline options
00077   for (arg=1;arg<argc;arg++) {
00078     if (0 == strcmp(argv[arg], "-h")) {
00079       print_usage(argv);
00080       return EXIT_SUCCESS;
00081     } else if (0 == strcmp(argv[arg], "-q")) {
00082       INFO("%s", "Quiet mode.");
00083       quiet_output = true;
00084     } else {
00085       ERR("%s is not supported option.", argv[arg]);
00086       print_usage(argv);
00087       return EXIT_FAILURE;
00088     }
00089   }
00090 
00091   // Display libnfc version
00092   printf("%s use libnfc %s\n", argv[0], acLibnfcVersion);
00093 
00094 #ifdef WIN32
00095   signal(SIGINT, (void (__cdecl*)(int)) intr_hdlr);
00096 #else
00097   signal(SIGINT, (void (*)()) intr_hdlr);
00098 #endif
00099 
00100   // Allocate memory to put the result of available devices listing
00101   if (!(pnddDevices = malloc (MAX_DEVICE_COUNT * sizeof (*pnddDevices)))) {
00102     fprintf (stderr, "malloc() failed\n");
00103     return EXIT_FAILURE;
00104   }
00105 
00106   // List available devices
00107   nfc_list_devices (pnddDevices, MAX_DEVICE_COUNT, &szFound);
00108 
00109   if (szFound < 2) {
00110     ERR("%zd device found but two connected devices are needed to relay NFC.", szFound);
00111     return EXIT_FAILURE;
00112   } 
00113 
00114   // Try to open the NFC emulator device
00115   pndTag = nfc_connect(&(pnddDevices[0]));
00116   if (pndTag == NULL)
00117   {
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   {
00130     ERR("%s", "Initialization of NFC emulator failed");
00131     nfc_disconnect(pndTag);
00132     return EXIT_FAILURE;
00133   }
00134   printf("%s", "Configuring emulator settings...");
00135   nfc_configure(pndTag,NDO_HANDLE_CRC,false);
00136   nfc_configure(pndTag,NDO_HANDLE_PARITY,false);
00137   nfc_configure(pndTag,NDO_ACCEPT_INVALID_FRAMES,true);
00138   printf("%s", "Done, emulated tag is initialized");
00139 
00140   // Try to open the NFC reader
00141   pndReader = nfc_connect(&(pnddDevices[1]));
00142   
00143   printf("Connected to the NFC reader device: %s", pndReader->acName);
00144   printf("%s", "Configuring NFC reader settings...");
00145   nfc_initiator_init(pndReader);
00146   nfc_configure(pndReader,NDO_HANDLE_CRC,false);
00147   nfc_configure(pndReader,NDO_HANDLE_PARITY,false);
00148   nfc_configure(pndReader,NDO_ACCEPT_INVALID_FRAMES,true);
00149   printf("%s", "Done, relaying frames now!");
00150 
00151   while(!quitting)
00152   {
00153     // Test if we received a frame from the reader
00154     if (nfc_target_receive_bits(pndTag,abtReaderRx,&szReaderRxBits,abtReaderRxPar))
00155     {
00156       // Drop down the field before sending a REQA command and start a new session
00157       if (szReaderRxBits == 7 && abtReaderRx[0] == 0x26)
00158       {
00159         // Drop down field for a very short time (original tag will reboot)
00160         nfc_configure(pndReader,NDO_ACTIVATE_FIELD,false);
00161         if(!quiet_output)
00162           printf("\n");
00163         nfc_configure(pndReader,NDO_ACTIVATE_FIELD,true);
00164       }
00165 
00166       // Print the reader frame to the screen
00167       if(!quiet_output)
00168       {
00169         printf("R: ");
00170         print_hex_par(abtReaderRx,szReaderRxBits,abtReaderRxPar);
00171       }
00172       // Forward the frame to the original tag
00173       if (nfc_initiator_transceive_bits(pndReader,abtReaderRx,szReaderRxBits,abtReaderRxPar,abtTagRx,&szTagRxBits,abtTagRxPar))
00174       {
00175         // Redirect the answer back to the reader
00176         nfc_target_send_bits(pndTag,abtTagRx,szTagRxBits,abtTagRxPar);
00177 
00178         // Print the tag frame to the screen
00179         if(!quiet_output)
00180         {
00181           printf("T: ");
00182           print_hex_par(abtTagRx,szTagRxBits,abtTagRxPar);
00183         }
00184       }
00185     }
00186   }
00187 
00188   nfc_disconnect(pndTag);
00189   nfc_disconnect(pndReader);
00190   exit(EXIT_SUCCESS);
00191 }

Generated on 4 Sep 2010 for libnfc by  doxygen 1.6.1