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