MFRC 522 with ATmega8. Mifare Classic 1K won't authenticate - nfc

I have a problem with an ATmega8 and Mifare RC-522 based NFC/RFID controller.
I'm using this library and I've managed to read the UID of a card.
However, I'd like to also read and write other parts of the card but whenever I try to use the MFRC522_Auth function I don't get the idle interrupt which I should, instead it gives me LoAlertIrq saying that FIFObuffer is almost empty.
Here are the docs for the reader and the card, and below are relevant parts of my code.
main.c :
byte = mfrc522_request(PICC_REQALL,str);
if(byte == CARD_FOUND)
{
byte = mfrc522_get_card_serial(str);
if(byte == CARD_FOUND)
{
byte = mfrc522_auth(PICC_AUTHENT1A, 7, sectorKeyA, str);
if( (byte == CARD_FOUND) )
{
byte = MFRC522_Read1(4, str);
if(byte == CARD_FOUND)
{
//write content of that block
}
}
}
Relevant functions from the library :
void mfrc522_write(uint8_t reg, uint8_t data)
{
ENABLE_CHIP();
spi_transmit((reg<<1)&0x7E);
spi_transmit(data);
DISABLE_CHIP();
}
uint8_t mfrc522_read(uint8_t reg)
{
uint8_t data;
ENABLE_CHIP();
spi_transmit(((reg<<1)&0x7E)|0x80);
data = spi_transmit(0x00);
DISABLE_CHIP();
return data;
}
uint8_t mfrc522_to_card(uint8_t cmd, uint8_t *send_data, uint8_t send_data_len, uint8_t *back_data, uint32_t *back_data_len)
{
uint8_t status = 0;
uint8_t irqEn = 0x00;
uint8_t waitIRq = 0x00;
uint8_t lastBits;
uint8_t n;
uint8_t tmp;
uint32_t i;
switch (cmd)
{
case MFAuthent_CMD: //Certification cards close
{
irqEn = 0x12;
waitIRq = 0x10;
break;
}
case Transceive_CMD: //Transmit FIFO data
{
irqEn = 0x77;
waitIRq = 0x30;
break;
}
default:
break;
}
mfrc522_write(ComIEnReg, irqEn|0x80); //Interrupt request
n=mfrc522_read(ComIrqReg);
mfrc522_write(ComIrqReg,n&(~0x80));//clear all interrupt bits
n=mfrc522_read(FIFOLevelReg);
mfrc522_write(FIFOLevelReg,n|0x80);//flush FIFO data
// mfrc522_write(CommandReg, Idle_CMD); //NO action; Cancel the current cmd???
n=mfrc522_read(CommandReg);
mfrc522_write(CommandReg,n|0x00);
//Writing data to the FIFO
for (i=0; i<send_data_len; i++)
{
mfrc522_write(FIFODataReg, send_data[i]);
}
//Execute the cmd
mfrc522_write(CommandReg, cmd);
if (cmd == Transceive_CMD)
{
n=mfrc522_read(BitFramingReg);
mfrc522_write(BitFramingReg,n|0x80);
}
//Waiting to receive data to complete
i = 2000; //i according to the clock frequency adjustment, the operator M1 card maximum waiting time 25ms???
while (1) {
n = mfrc522_read(ComIrqReg); // ComIrqReg[7..0] bits are: Set1 TxIRq RxIRq IdleIRq HiAlertIRq LoAlertIRq ErrIRq TimerIRq
if (n & waitIRq) { // One of the interrupts that signal success has been set.
break;
}
if (n & 0x01) { // Timer interrupt - nothing received in 25ms
// return 6; //debug purpose
if (cmd == MFAuthent_CMD) {
LCD_Clear();
LCD_WriteTextXY(1, 3, LCD_itoa( mfrc522_read(ComIrqReg) ) );
_delay_ms(2500);
}
break;
}
if (--i == 0) { // The emergency break. If all other condions fail we will eventually terminate on this one after 35.7ms. Communication with the MFRC522 might be down.
if (cmd == MFAuthent_CMD) {
LCD_Clear();
LCD_WriteTextXY(1, 3, LCD_itoa( mfrc522_read(ComIrqReg) ) );
_delay_ms(2500);
}
break;
}
}
tmp=mfrc522_read(BitFramingReg);
mfrc522_write(BitFramingReg,tmp&(~0x80));
if (i != 0)
{
if(!(mfrc522_read(ErrorReg) & 0x1B)) //BufferOvfl Collerr CRCErr ProtecolErr
{
status = CARD_FOUND;
if (n & irqEn & 0x01)
{
status = CARD_NOT_FOUND; //??
}
if (cmd == Transceive_CMD)
{
n = mfrc522_read(FIFOLevelReg);
lastBits = mfrc522_read(ControlReg) & 0x07;
if (lastBits)
{
*back_data_len = (n-1)*8 + lastBits;
}
else
{
*back_data_len = n*8;
}
if (n == 0)
{
n = 1;
}
if (n > MAX_LEN)
{
n = MAX_LEN;
}
//Reading the received data in FIFO
for (i=0; i<n; i++)
{
back_data[i] = mfrc522_read(FIFODataReg);
}
}
}
if (cmd == MFAuthent_CMD) {
LCD_WriteTextXY(1, 10, LCD_itoa16( mfrc522_read(Status2Reg) ) );
_delay_ms(2500);
}
} else status = 9;
return status;
}
uint8_t mfrc522_get_card_serial(uint8_t * serial_out)
{
uint8_t status;
uint8_t i;
uint8_t serNumCheck=0;
uint32_t unLen;
mfrc522_write(BitFramingReg, 0x00); //TxLastBists = BitFramingReg[2..0]
serial_out[0] = PICC_ANTICOLL;
serial_out[1] = 0x20;
status = mfrc522_to_card(Transceive_CMD, serial_out, 2, serial_out, &unLen);
if (status == CARD_FOUND)
{
//Check card serial number
for (i=0; i<4; i++)
{
serNumCheck ^= serial_out[i];
}
if (serNumCheck != serial_out[i])
{
status = ERROR;
}
}
return status;
}
uint8_t mfrc522_auth(uint8_t authMode, uint8_t BlockAddr, uint8_t *Sectorkey, uint8_t *serNum)
{
uint8_t status;
uint32_t recvBits;
uint8_t i;
uint8_t buff[12];
// Validate instruction block address + sector + password + card serial number
buff[0] = authMode;
buff[1] = BlockAddr;
for (i=0; i<6; i++)
{
buff[i+2] = 0xFF /**(Sectorkey+i)*/;
}
for (i=0; i<4; i++)
{
buff[i+8] = *(serNum+i);
}
status = mfrc522_to_card(MFAuthent_CMD, buff, 12, buff, &recvBits);
return status;
}
uint8_t MFRC522_Read1(uint8_t blockAddr, uint8_t *recvData)
{
uint8_t status = 0;
uint8_t unLen, efa;
recvData[0] = PICC_READ;
recvData[1] = blockAddr;
CalculateCRC(recvData, 2, &recvData);
status = mfrc522_to_card(Transceive_CMD, recvData, 4, recvData, &unLen);
if ((status != CARD_FOUND)|| (unLen != 0x90))
{
status = ERROR;
}
return status;
}
uint8_t CalculateCRC(uint8_t *pIndata, uint8_t len, uint8_t *pOutData)
{
uint8_t i, n;
uint8_t status = 0;
n = mfrc522_read(DivIrqReg);
mfrc522_write(DivIrqReg,n&(~0x04)); //CRCIrq = 0
n = mfrc522_read(FIFOLevelReg); //FIFO
mfrc522_write(FIFOLevelReg, n|0x80);
//Write_MFRC522(CommandReg, PCD_IDLE);
// Write data to the FIFO
for (i=0; i<len; i++)
{
mfrc522_write(FIFODataReg, *(pIndata+i));
}
mfrc522_write(CommandReg, CalcCRC_CMD);
// Read the CRC calculation result
i = 0xFF;
while(1){
n = mfrc522_read(DivIrqReg);
if (n & 0x04) {
break;
}
if (--i != 0) {
return 7;
}
}
// Read the CRC calculation result
pOutData[3] = mfrc522_read(CRCResultReg_2);
pOutData[4] = mfrc522_read(CRCResultReg_1);
return status = 0;
}

Related

ESP32 IDF, rewrite SPI custom function to meet the specific of the device

I'm trying to use the esp-idf standard SPI management functions instead of custom ones.
The custom functions are:
// the initialization of the gpio:
void _spi_init(pn532_t *obj, uint8_t clk, uint8_t miso, uint8_t mosi, uint8_t ss)
{
obj->_clk = clk;
obj->_miso = miso;
obj->_mosi = mosi;
obj->_ss = ss;
gpio_pad_select_gpio(obj->_clk);
gpio_pad_select_gpio(obj->_miso);
gpio_pad_select_gpio(obj->_mosi);
gpio_pad_select_gpio(obj->_ss);
gpio_set_direction(obj->_ss, GPIO_MODE_OUTPUT);
gpio_set_level(obj->_ss, 1);
gpio_set_direction(obj->_clk, GPIO_MODE_OUTPUT);
gpio_set_direction(obj->_mosi, GPIO_MODE_OUTPUT);
gpio_set_direction(obj->_miso, GPIO_MODE_INPUT);
}
// read and write to SPI
uint8_t _spi_read(pn532_t *obj)
{
int8_t i, x;
x = 0;
gpio_set_level(obj->_clk, 1);
for (i = 0; i < 8; i++)
{
if (gpio_get_level(obj->_miso))
{
x |= _BV(i);
}
gpio_set_level(obj->_clk, 0);
gpio_set_level(obj->_clk, 1);
}
return x;
}
void _spi_write(pn532_t *obj, uint8_t c)
{
int8_t i;
gpio_set_level(obj->_clk, 1);
for (i = 0; i < 8; i++)
{
gpio_set_level(obj->_clk, 0);
if (c & _BV(i))
{
gpio_set_level(obj->_mosi, 1);
}
else
{
gpio_set_level(obj->_mosi, 0);
}
gpio_set_level(obj->_clk, 1);
}
}
My refactoring currently is only for these 3 functions:
void _spi_init(pn532_t *obj, spi_host_device_t spiHostDevice, uint8_t ss) {
// the spi_bus_initialize is already initialized in the main function.
gpio_set_direction((gpio_num_t) ss, GPIO_MODE_OUTPUT);
gpio_set_level((gpio_num_t) ss, 1);
//Config Frequency and SS GPIO
spi_device_interface_config_t deviceInterfaceConfig = {
.mode = 0, //SPI mode 0
.clock_speed_hz= 1200000, // Usually 1.2 Mhz
.input_delay_ns = 0,
.spics_io_num = ss,
.flags = SPI_DEVICE_BIT_LSBFIRST, // the device use LSB
.queue_size = 1
};
spi_device_handle_t spiDeviceHandle;
//Attach the pn532 to the SPI bus
ESP_ERROR_CHECK(spi_bus_add_device(spiHostDevice, &deviceInterfaceConfig, &spiDeviceHandle));
obj->spi = spiDeviceHandle;
}
void _spi_write(pn532_t *obj, uint8_t data) {
spi_transaction_t t;
memset(&t, 0, sizeof(t)); //Zero out the transaction
t.length = 8;
t.tx_buffer = &data;
ESP_LOGI(TAG, "send data: 0b%s", toBinary(data,8));
ESP_ERROR_CHECK(spi_device_polling_transmit(obj->spi, &t));
}
uint8_t _spi_read(pn532_t *obj) {
uint8_t data = 1;
spi_transaction_t t;
memset(&t, 0, sizeof(t)); //Zero out the transaction
t.length = 8;
t.rxlength = 8;
t.tx_buffer = NULL;
t.rx_buffer = &data;
ESP_ERROR_CHECK(spi_device_polling_transmit(obj->spi, &t));
ESP_LOGI(TAG, "read data: 0b%s", toBinary(data,8));
return data;
}
Currently, this rewrite is not working. I already did a lot of tries with any combination of config that makes sense, without success.
Practically, when I ask the device to give me the status, I'm expecting one byte in response, in form of 0x00 or 0x01. But I'm receiving 0x08. So still one bit up, but in the wrong position.
So I think I'm still missing some configuration on my rewrite.
Apprising any hit or test that I can do in order to found what is missing!
Thanks!

How do I allocate memory for LabVIEW array of clusters using DSSetHandleSize() without a memory exception

I am able to reliably use DSSetHandleSize() with arrays of LabVIEW strings. When I try the same with arrays of clusters, it always crashes upon return from the DLL when increasing the handle size.
The code is:
typedef struct {
uint8_t depth;
LStrHandle name;
LStrHandle child;
} TreeElem;
typedef struct {
int32_t dimSize;
TreeElem Element[1];
} **TreeHdl;
MSEXPORT void BuildTreeCtl(int32_t depth, uint32_t xmlNodePtr, TreeHdl TreeCluster)
{
xmlNode *cur_node, *chile_node;
for (cur_node = (xmlNode *) xmlNodePtr; cur_node; cur_node = cur_node->next) {
if (cur_node->type == XML_ELEMENT_NODE) {
DSSetHandleSize(TreeCluster, sizeof(int32) + (sizeof(TreeElem) * ((*TreeCluster)->dimSize + 1)));
int idx = (*TreeCluster)->dimSize++;
if (cur_node->name != NULL) {
LV_STR_NEW(((*TreeCluster)->Element)[idx].name, (char*) cur_node->name);}
// check for CDATA
for (chile_node = cur_node->children; chile_node; chile_node = chile_node->next) {
if (chile_node->type == XML_CDATA_SECTION_NODE) {
if (chile_node->content != NULL) {
LV_STR_NEW(((*TreeCluster)->Element)[idx].child, (char*) chile_node->content);
}
}
}
BuildTreeCtl(depth + 1, (uint32_t) cur_node->children, TreeCluster);
}
}
}
Call DSSetHSzClr instead of DSSetHandleSize.
It turns out DSSetHandleSize() (for at least LabVIEW 2013 and earlier) does not initialize new memory to zero when increasing array size. Also, it's likely to allocate a new block of memory with a different handle than when going in - it does reliably transfer existing data to the new memory allocation, but whatever exists in the new memory block will cause LabVIEW to crash on return, certainly because LabVIEW is using junk pointers.
The code should be:
MSEXPORT void BuildTreeCtl(int32_t depth, uint32_t xmlNodePtr, TreeHdl TreeCluster)
{
xmlNode *cur_node, *chile_node;
for (cur_node = (xmlNode *) xmlNodePtr; cur_node; cur_node = cur_node->next) {
if (cur_node->type == XML_ELEMENT_NODE) {
DSSetHandleSize(TreeCluster, sizeof(int32) + (sizeof(TreeElem) * ((*TreeCluster)->dimSize + 1)));
int idx = (*TreeCluster)->dimSize++;
#if 0 // brute force
(((*TreeCluster)->Element)[idx]).depth = depth;
(((*TreeCluster)->Element)[idx]).name = NULL;
(((*TreeCluster)->Element)[idx]).child = NULL;
#elif 0 // generic
uint8_t *Ptr = (uint8_t *) &(((*TreeCluster)->Element)[idx]);
for (int j=0; j<sizeof(TreeElem); j++) {*(Ptr + j) = 0;}
#else
uint8_t *Ptr = (uint8_t *) &(((*TreeCluster)->Element)[idx]);
memset(Ptr, 0, sizeof(TreeElem));
#endif
if (cur_node->name != NULL) {
LV_STR_NEW(((*TreeCluster)->Element)[idx].name, (char*) cur_node->name);}
// check for CDATA
for (chile_node = cur_node->children; chile_node; chile_node = chile_node->next) {
if (chile_node->type == XML_CDATA_SECTION_NODE) {
if (chile_node->content != NULL) {
LV_STR_NEW(((*TreeCluster)->Element)[idx].child, (char*) chile_node->content);
}
}
}
BuildTreeCtl(depth + 1, (uint32_t) cur_node->children, TreeCluster);
}
}
}

Unable to communicate between libwebsocket as client and socket.io as server

This is client code by using libwebsocket version 1.5
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <string.h>
#include <assert.h>
#include <signal.h>
#include <syslog.h>
#include <sys/time.h>
#include <unistd.h>
#include <libwebsockets.h>
static volatile int force_exit = 0;
static int state, command_received = 0, forked = 0;
#define MAX_ECHO_PAYLOAD 1400
#define LOCAL_RESOURCE_PATH "./"
struct per_session_data {
unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + MAX_ECHO_PAYLOAD + LWS_SEND_BUFFER_POST_PADDING];
unsigned int len;
};
//for temporary storing data from tcpdump
struct per_session_data data1;
static int callback_echo(struct libwebsocket_context *context, struct libwebsocket *wsi, enum libwebsocket_callback_reasons reason, void *user, void *in, size_t len)
{
struct per_session_data *pss = (struct per_session_data *)user;
int n;
switch (reason) {
/* when the callback is used for client operations --> */
case LWS_CALLBACK_CLOSED:
case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
printf("Closed\n");
state = 0;
break;
case LWS_CALLBACK_ESTABLISHED:
case LWS_CALLBACK_CLIENT_ESTABLISHED:
printf("Client connected\n");
state = 2;
break;
/* we will receive our packet here*/
case LWS_CALLBACK_RECEIVE:
case LWS_CALLBACK_CLIENT_RECEIVE:
printf("Rx from server: %s\n", (char *)in);
if (!strcmp((char *)in, "tcpdump"))
{
command_received = 1;
}
break;
/* we will send our packet here */
case LWS_CALLBACK_CLIENT_WRITEABLE:
printf("client writing to server\n");
pss->len = sprintf((char *)&pss->buf[LWS_SEND_BUFFER_PRE_PADDING], "%s", data1.buf + LWS_SEND_BUFFER_PRE_PADDING);
n = libwebsocket_write(wsi, &pss->buf[LWS_SEND_BUFFER_PRE_PADDING], pss->len, LWS_WRITE_TEXT);
printf("Data: %s\n\n\n\n\n\n\n", &pss->buf[LWS_SEND_BUFFER_PRE_PADDING]);
//error handling for write fail and partial writes
if (n < 0) {
printf("ERROR %d writing to socket, hanging up\n", n);
return -1;
}
if (n < (int)pss->len) {
printf("Partial write\n");
return -1;
}
break;
default:
printf("default...\n");
break;
}
return 0;
}
/* List of available protocols */
static struct libwebsocket_protocols protocols[] = {
{
"default", /* name */
callback_echo, /* callback */
sizeof(struct per_session_data) /* per_session_data_size */
},
{
NULL, NULL, 0 /* End of list */
}
};
void sighandler(int sig)
{
force_exit = 1;
}
int main(int argc, char **argv)
{
//pipe stuff
int pipe_fd[2];
if (pipe(pipe_fd) < 0)
{
perror("PIPE:");
exit(-1);
}
//for libwebsocket_service
int n = 0;
//test port can be overidden
int port = 9000;
struct libwebsocket_context *context;
int opts = 0;
char interface_name[128] = "";
const char *interface = NULL;
int use_ssl = 0;
char ssl_cert[256] = LOCAL_RESOURCE_PATH"/libwebsockets-test-server.pem";
char ssl_key[256] = LOCAL_RESOURCE_PATH"/libwebsockets-test-server.key.pem";
int listen_port = 80;
struct lws_context_creation_info info;
char passphrase[256];
char uri[256] = "/";
char address[256], ads_port[256 + 30];
//lws servicing time intervals
int rate_us = 250000;
unsigned int oldus = 0;
struct libwebsocket *wsi;
//should check this
int debug_level = 2;
memset(&info, 0, sizeof info);
lwsl_notice("Built to support client operations\n");
//re-configuring server ip and port here
if (argc == 3)
{
strncpy(address, argv[1], sizeof(address) - 1);
address[sizeof(address) - 1] = '\0';
port = atoi(argv[2]);
}
else if (argc == 1)
{
strncpy(address, "localhost", sizeof(address) - 1);
address[sizeof(address) - 1] = '\0';
port = 9000;
}
else
{
printf("Try: ./client.exec <ip> <port>\n");
exit(-1);
}
/* we will only try to log things according to our debug_level */
setlogmask(LOG_UPTO (LOG_DEBUG));
openlog("lwsts", 0, LOG_DAEMON);
/* tell the library what debug level to emit and to send it to syslog */
lws_set_log_level(debug_level, lwsl_emit_syslog);
lwsl_notice("libwebsockets echo test - "
"(C) Copyright 2010-2015 Andy Green <andy#warmcat.com> - "
"licensed under LGPL2.1\n");
lwsl_notice("Running in client mode\n");
listen_port = CONTEXT_PORT_NO_LISTEN;
lwsl_info("requiring server cert validation againts %s\n", ssl_cert);
info.ssl_ca_filepath = ssl_cert;
info.port = listen_port;
info.iface = interface;
info.protocols = protocols;
#ifndef LWS_NO_EXTENSIONS
info.extensions = libwebsocket_get_internal_extensions();
#endif
info.gid = -1;
info.uid = -1;
info.options = opts;
context = libwebsocket_create_context(&info);
if (context == NULL) {
lwsl_err("libwebsocket init failed\n");
return -1;
}
signal(SIGINT, sighandler);
n = 0;
while (n >= 0 && !force_exit)
{
//do connect only once
if (!state) {
state = 1;
printf("Client connecting to %s:%u....\n", address, port);
address[sizeof(address) - 1] = '\0';
sprintf(ads_port, "%s:%u", address, port & 65535);
wsi = libwebsocket_client_connect(context, address, port, use_ssl, uri, ads_port, ads_port, NULL, -1);
if (!wsi) {
printf("Client failed to connect to %s:%u\n", address, port);
goto bail;
}
}
if (command_received == 1 && !forked)
{
printf("Going to fork\n");
forked = 1;
pid_t child_pid = fork();
if (child_pid == -1)
{
perror("FORK:");
exit(-1);
}
else if (child_pid == 0)
{
close(pipe_fd[0]);
printf("Starting tcpdump\n");
if (dup2(pipe_fd[1], 1) < 0)
{
perror("DUP2:");
exit(-1);
}
//closing the connection to server for child
libwebsocket_context_destroy(context);
closelog();
char *cmd[] = {"tcpdump", "-i", "any", NULL};
if (execv("/usr/sbin/tcpdump", cmd) < 0)
{
perror("EXECV:");
exit(-1);
}
}
}
/* if (forked == 1)
{
close(pipe_fd[1]);
}
*/
if (command_received == 1)
{
//stay here if the pipe is empty else try to read max 1400 bytes of data
while ((data1.len = read(pipe_fd[0], data1.buf + LWS_SEND_BUFFER_PRE_PADDING, 1400)) <= 0);
//check if server wants any service
//printf("%s\n\n\n\n\n\n\n", data1.buf + LWS_SEND_BUFFER_PRE_PADDING);
libwebsocket_callback_on_writable(context, wsi);
}
//This fn times out every 10usec
n = libwebsocket_service(context, 10);
}
//bail: jump from while loop also if connect fails
bail:
libwebsocket_context_destroy(context);
printf("libwebsockets-test-echo exited cleanly\n");
closelog();
return 0;
}
This is my server code by using socket.io
var io = require('socket.io')();
var middleware = require('socketio-wildcard')();
io.use(middleware);
io.on('connection', function(socket) {
console.log('On socket connection')
socket.on('*', function(event, data){
console.log("---- Event ----- : " + JSON.stringify(event));
console.log("---- Data ----- : " + JSON.stringify(data))
});
});
io.listen(9000, 'localhost');
The client is unable to connect with server. when i tested client with strace it infinitely does receive as below
recv(8, "", 1, 0) = 0
recv(8, "", 1, 0) = 0
recv(8, "", 1, 0) = 0
.
.
.
.
Please point out my mistake. Any help is appreciated.
Thanks

need Help in windivert webfilter

Hello every one i m trying to develop web filter and i found Win Divert Samples
here the code is i m trying to run in visual Studio 12 and got this error
IntelliSense: argument of type "PVOID" is incompatible with parameter of type "char *"
#include <winsock2.h>
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include "windivert.h"
#define MAXBUF 0xFFFF
#define MAXURL 4096
/*
* URL and blacklist representation.
*/
typedef struct
{
char *domain;
char *uri;
} URL, *PURL;
typedef struct
{
UINT size;
UINT length;
PURL *urls;
} BLACKLIST, *PBLACKLIST;
/*
* Pre-fabricated packets.
*/
typedef struct
{
WINDIVERT_IPHDR ip;
WINDIVERT_TCPHDR tcp;
} PACKET, *PPACKET;
typedef struct
{
PACKET header;
UINT8 data[];
} DATAPACKET, *PDATAPACKET;
/*
* THe block page contents.
*/
const char block_data[] =
"HTTP/1.1 200 OK\r\n"
"Connection: close\r\n"
"Content-Type: text/html\r\n"
"\r\n"
"<!doctype html>\n"
"<html>\n"
"\t<head>\n"
"\t\t<title>BLOCKED!</title>\n"
"\t</head>\n"
"\t<body>\n"
"\t\t<h1>BLOCKED!</h1>\n"
"\t\t<hr>\n"
"\t\t<p>This URL has been blocked!</p>\n"
"\t</body>\n"
"</html>\n";
/*
* Prototypes
*/
static void PacketInit(PPACKET packet);
static int __cdecl UrlCompare(const void *a, const void *b);
static int UrlMatch(PURL urla, PURL urlb);
static PBLACKLIST BlackListInit(void);
static void BlackListInsert(PBLACKLIST blacklist, PURL url);
static void BlackListSort(PBLACKLIST blacklist);
static BOOL BlackListMatch(PBLACKLIST blacklist, PURL url);
static void BlackListRead(PBLACKLIST blacklist, const char *filename);
static BOOL BlackListPayloadMatch(PBLACKLIST blacklist, char *data,
UINT16 len);
/*
* Entry.
*/
int __cdecl main(int argc, char **argv)
{
HANDLE handle;
WINDIVERT_ADDRESS addr;
UINT8 packet[MAXBUF];
UINT packet_len;
PWINDIVERT_IPHDR ip_header;
PWINDIVERT_TCPHDR tcp_header;
PVOID payload;
UINT payload_len;
PACKET reset0;
PPACKET reset = &reset0;
PACKET finish0;
PPACKET finish = &finish0;
PDATAPACKET blockpage;
UINT16 blockpage_len;
PBLACKLIST blacklist;
unsigned i;
INT16 priority = 404; // Arbitrary.
// Read the blacklists.
if (argc <= 1)
{
fprintf(stderr, "usage: %s blacklist.txt [blacklist2.txt ...]\n",
argv[0]);
exit(EXIT_FAILURE);
}
blacklist = BlackListInit();
for (i = 1; i < (UINT)argc; i++)
{
BlackListRead(blacklist, argv[i]);
}
BlackListSort(blacklist);
// Initialize the pre-frabricated packets:
blockpage_len = sizeof(DATAPACKET)+sizeof(block_data)-1;
blockpage = (PDATAPACKET)malloc(blockpage_len);
if (blockpage == NULL)
{
fprintf(stderr, "error: memory allocation failed\n");
exit(EXIT_FAILURE);
}
PacketInit(&blockpage->header);
blockpage->header.ip.Length = htons(blockpage_len);
blockpage->header.tcp.SrcPort = htons(80);
blockpage->header.tcp.Psh = 1;
blockpage->header.tcp.Ack = 1;
memcpy(blockpage->data, block_data, sizeof(block_data)-1);
PacketInit(reset);
reset->tcp.Rst = 1;
reset->tcp.Ack = 1;
PacketInit(finish);
finish->tcp.Fin = 1;
finish->tcp.Ack = 1;
// Open the Divert device:
handle = WinDivertOpen(
"outbound && " // Outbound traffic only
"ip && " // Only IPv4 supported
"tcp.DstPort == 80 && " // HTTP (port 80) only
"tcp.PayloadLength > 0", // TCP data packets only
WINDIVERT_LAYER_NETWORK, priority, 0
);
if (handle == INVALID_HANDLE_VALUE)
{
fprintf(stderr, "error: failed to open the WinDivert device (%d)\n",
GetLastError());
exit(EXIT_FAILURE);
}
printf("OPENED WinDivert\n");
// Main loop:
while (TRUE)
{
if (!WinDivertRecv(handle, packet, sizeof(packet), &addr, &packet_len))
{
fprintf(stderr, "warning: failed to read packet (%d)\n",
GetLastError());
continue;
}
if (!WinDivertHelperParsePacket(packet, packet_len, &ip_header, NULL,
NULL, NULL, &tcp_header, NULL, &payload, &payload_len) ||
!BlackListPayloadMatch(blacklist, payload, (UINT16)payload_len))
{
// Packet does not match the blacklist; simply reinject it.
if (!WinDivertSend(handle, packet, packet_len, &addr, NULL))
{
fprintf(stderr, "warning: failed to reinject packet (%d)\n",
GetLastError());
}
continue;
}
// The URL matched the blacklist; we block it by hijacking the TCP
// connection.
// (1) Send a TCP RST to the server; immediately closing the
// connection at the server's end.
reset->ip.SrcAddr = ip_header->SrcAddr;
reset->ip.DstAddr = ip_header->DstAddr;
reset->tcp.SrcPort = tcp_header->SrcPort;
reset->tcp.DstPort = htons(80);
reset->tcp.SeqNum = tcp_header->SeqNum;
reset->tcp.AckNum = tcp_header->AckNum;
WinDivertHelperCalcChecksums((PVOID)reset, sizeof(PACKET), 0);
if (!WinDivertSend(handle, (PVOID)reset, sizeof(PACKET), &addr, NULL))
{
fprintf(stderr, "warning: failed to send reset packet (%d)\n",
GetLastError());
}
// (2) Send the blockpage to the browser:
blockpage->header.ip.SrcAddr = ip_header->DstAddr;
blockpage->header.ip.DstAddr = ip_header->SrcAddr;
blockpage->header.tcp.DstPort = tcp_header->SrcPort;
blockpage->header.tcp.SeqNum = tcp_header->AckNum;
blockpage->header.tcp.AckNum =
htonl(ntohl(tcp_header->SeqNum) + payload_len);
WinDivertHelperCalcChecksums((PVOID)blockpage, blockpage_len, 0);
addr.Direction = !addr.Direction; // Reverse direction.
if (!WinDivertSend(handle, (PVOID)blockpage, blockpage_len, &addr,
NULL))
{
fprintf(stderr, "warning: failed to send block page packet (%d)\n",
GetLastError());
}
// (3) Send a TCP FIN to the browser; closing the connection at the
// browser's end.
finish->ip.SrcAddr = ip_header->DstAddr;
finish->ip.DstAddr = ip_header->SrcAddr;
finish->tcp.SrcPort = htons(80);
finish->tcp.DstPort = tcp_header->SrcPort;
finish->tcp.SeqNum =
htonl(ntohl(tcp_header->AckNum) + sizeof(block_data) - 1);
finish->tcp.AckNum =
htonl(ntohl(tcp_header->SeqNum) + payload_len);
WinDivertHelperCalcChecksums((PVOID)finish, sizeof(PACKET), 0);
if (!WinDivertSend(handle, (PVOID)finish, sizeof(PACKET), &addr, NULL))
{
fprintf(stderr, "warning: failed to send finish packet (%d)\n",
GetLastError());
}
}
}
/*
* Initialize a PACKET.
*/
static void PacketInit(PPACKET packet)
{
memset(packet, 0, sizeof(PACKET));
packet->ip.Version = 4;
packet->ip.HdrLength = sizeof(WINDIVERT_IPHDR) / sizeof(UINT32);
packet->ip.Length = htons(sizeof(PACKET));
packet->ip.TTL = 64;
packet->ip.Protocol = IPPROTO_TCP;
packet->tcp.HdrLength = sizeof(WINDIVERT_TCPHDR) / sizeof(UINT32);
}
/*
* Initialize an empty blacklist.
*/
static PBLACKLIST BlackListInit(void)
{
PBLACKLIST blacklist = (PBLACKLIST)malloc(sizeof(BLACKLIST));
UINT size;
if (blacklist == NULL)
{
goto memory_error;
}
size = 1024;
blacklist->urls = (PURL *)malloc(size*sizeof(PURL));
if (blacklist->urls == NULL)
{
goto memory_error;
}
blacklist->size = size;
blacklist->length = 0;
return blacklist;
memory_error:
fprintf(stderr, "error: failed to allocate memory\n");
exit(EXIT_FAILURE);
}
/*
* Insert a URL into a blacklist.
*/
static void BlackListInsert(PBLACKLIST blacklist, PURL url)
{
if (blacklist->length >= blacklist->size)
{
blacklist->size = (blacklist->size*3) / 2;
printf("GROW blacklist to %u\n", blacklist->size);
blacklist->urls = (PURL *)realloc(blacklist->urls,
blacklist->size*sizeof(PURL));
if (blacklist->urls == NULL)
{
fprintf(stderr, "error: failed to reallocate memory\n");
exit(EXIT_FAILURE);
}
}
blacklist->urls[blacklist->length++] = url;
}
/*
* Sort the blacklist (for searching).
*/
static void BlackListSort(PBLACKLIST blacklist)
{
qsort(blacklist->urls, blacklist->length, sizeof(PURL), UrlCompare);
}
/*
* Match a URL against the blacklist.
*/
static BOOL BlackListMatch(PBLACKLIST blacklist, PURL url)
{
int lo = 0, hi = ((int)blacklist->length)-1;
while (lo <= hi)
{
INT mid = (lo + hi) / 2;
int cmp = UrlMatch(url, blacklist->urls[mid]);
if (cmp > 0)
{
hi = mid-1;
}
else if (cmp < 0)
{
lo = mid+1;
}
else
{
return TRUE;
}
}
return FALSE;
}
/*
* Read URLs from a file.
*/
static void BlackListRead(PBLACKLIST blacklist, const char *filename)
{
char domain[MAXURL+1];
char uri[MAXURL+1];
int c;
UINT16 i, j;
PURL url;
FILE *file = fopen(filename, "r");
if (file == NULL)
{
fprintf(stderr, "error: could not open blacklist file %s\n",
filename);
exit(EXIT_FAILURE);
}
// Read URLs from the file and add them to the blacklist:
while (TRUE)
{
while (isspace(c = getc(file)))
;
if (c == EOF)
{
break;
}
if (c != '-' && !isalnum(c))
{
while (!isspace(c = getc(file)) && c != EOF)
;
if (c == EOF)
{
break;
}
continue;
}
i = 0;
domain[i++] = (char)c;
while ((isalnum(c = getc(file)) || c == '-' || c == '.') && i < MAXURL)
{
domain[i++] = (char)c;
}
domain[i] = '\0';
j = 0;
if (c == '/')
{
while (!isspace(c = getc(file)) && c != EOF && j < MAXURL)
{
uri[j++] = (char)c;
}
uri[j] = '\0';
}
else if (isspace(c))
{
uri[j] = '\0';
}
else
{
while (!isspace(c = getc(file)) && c != EOF)
;
continue;
}
printf("ADD %s/%s\n", domain, uri);
url = (PURL)malloc(sizeof(URL));
if (url == NULL)
{
goto memory_error;
}
url->domain = (char *)malloc((i+1)*sizeof(char));
url->uri = (char *)malloc((j+1)*sizeof(char));
if (url->domain == NULL || url->uri == NULL)
{
goto memory_error;
}
strcpy(url->uri, uri);
for (j = 0; j < i; j++)
{
url->domain[j] = domain[i-j-1];
}
url->domain[j] = '\0';
BlackListInsert(blacklist, url);
}
fclose(file);
return;
memory_error:
fprintf(stderr, "error: memory allocation failed\n");
exit(EXIT_FAILURE);
}
/*
* Attempt to parse a URL and match it with the blacklist.
*
* BUG:
* - This function makes several assumptions about HTTP requests, such as:
* 1) The URL will be contained within one packet;
* 2) The HTTP request begins at a packet boundary;
* 3) The Host header immediately follows the GET/POST line.
* Some browsers, such as Internet Explorer, violate these assumptions
* and therefore matching will not work.
*/
static BOOL BlackListPayloadMatch(PBLACKLIST blacklist, char *data, UINT16 len)
{
static const char get_str[] = "GET /";
static const char post_str[] = "POST /";
static const char http_host_str[] = " HTTP/1.1\r\nHost: ";
char domain[MAXURL];
char uri[MAXURL];
URL url = {domain, uri};
UINT16 i = 0, j;
BOOL result;
HANDLE console;
if (len <= sizeof(post_str) + sizeof(http_host_str))
{
return FALSE;
}
if (strncmp(data, get_str, sizeof(get_str)-1) == 0)
{
i += sizeof(get_str)-1;
}
else if (strncmp(data, post_str, sizeof(post_str)-1) == 0)
{
i += sizeof(post_str)-1;
}
else
{
return FALSE;
}
for (j = 0; i < len && data[i] != ' '; j++, i++)
{
uri[j] = data[i];
}
uri[j] = '\0';
if (i + sizeof(http_host_str)-1 >= len)
{
return FALSE;
}
if (strncmp(data+i, http_host_str, sizeof(http_host_str)-1) != 0)
{
return FALSE;
}
i += sizeof(http_host_str)-1;
for (j = 0; i < len && data[i] != '\r'; j++, i++)
{
domain[j] = data[i];
}
if (i >= len)
{
return FALSE;
}
if (j == 0)
{
return FALSE;
}
if (domain[j-1] == '.')
{
// Nice try...
j--;
if (j == 0)
{
return FALSE;
}
}
domain[j] = '\0';
printf("URL %s/%s: ", domain, uri);
// Reverse the domain:
for (i = 0; i < j / 2; i++)
{
char t = domain[i];
domain[i] = domain[j-i-1];
domain[j-i-1] = t;
}
// Search the blacklist:
result = BlackListMatch(blacklist, &url);
// Print the verdict:
console = GetStdHandle(STD_OUTPUT_HANDLE);
if (result)
{
SetConsoleTextAttribute(console, FOREGROUND_RED);
puts("BLOCKED!");
}
else
{
SetConsoleTextAttribute(console, FOREGROUND_GREEN);
puts("allowed");
}
SetConsoleTextAttribute(console,
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
return result;
}
/*
* URL comparison.
*/
static int __cdecl UrlCompare(const void *a, const void *b)
{
PURL urla = *(PURL *)a;
PURL urlb = *(PURL *)b;
int cmp = strcmp(urla->domain, urlb->domain);
if (cmp != 0)
{
return cmp;
}
return strcmp(urla->uri, urlb->uri);
}
/*
* URL matching
*/
static int UrlMatch(PURL urla, PURL urlb)
{
UINT16 i;
for (i = 0; urla->domain[i] && urlb->domain[i]; i++)
{
int cmp = (int)urlb->domain[i] - (int)urla->domain[i];
if (cmp != 0)
{
return cmp;
}
}
if (urla->domain[i] == '\0' && urlb->domain[i] != '\0')
{
return 1;
}
for (i = 0; urla->uri[i] && urlb->uri[i]; i++)
{
int cmp = (int)urlb->uri[i] - (int)urla->uri[i];
if (cmp != 0)
{
return cmp;
}
}
if (urla->uri[i] == '\0' && urlb->uri[i] != '\0')
{
return 1;
}
return 0;
}
This file compiles without errors as C code, so be sure that you compile it as C. If you need to compile it as C++, then add explicit cast to char* at payload parameter in this line:
if (!WinDivertHelperParsePacket(packet, packet_len, &ip_header, NULL,
NULL, NULL, &tcp_header, NULL, &payload, &payload_len) ||
!BlackListPayloadMatch(blacklist, payload, (UINT16)payload_len))
Like this:
if (!WinDivertHelperParsePacket(packet, packet_len, &ip_header, NULL,
NULL, NULL, &tcp_header, NULL, &payload, &payload_len) ||
!BlackListPayloadMatch(blacklist, (char*)payload, (UINT16)payload_len))

Mac C++ Broadcast -> more then one network-interface

I have a broadcast program on my mac, everything is working fine, but if i have more then one network interface, he didn't recieve anything.
So what i now want to do is:
Check which network interfaces are activ on the mac
send to every activ interface a broadcast ( so i have to select which interface i want to use)
recieve the answer (if there is one :) )
Interesting:
the broadcast client is on my WLAN (with a router beetween the devices) and a normal internet connection is on my LAN. If i deactivate the LAN in the system configs, he also didn't find my other device, but if i pull the cable he found the other device... So maybe i didn't have to look which interface is activ and have a look to which interface is connected.
Do u have some tipps or good google keywords for me to do that?
Long time ago, but if someone find my post, here is my solution:
#include <stdint.h>
static uint32 Inet_AtoN(const char * buf)
{
// net_server inexplicably doesn't have this function; so I'll just fake it
uint32 ret = 0;
int shift = 24; // fill out the MSB first
bool startQuad = true;
while ((shift >= 0) && (*buf))
{
if (startQuad)
{
unsigned char quad = (unsigned char)atoi(buf);
ret |= (((uint32)quad) << shift);
shift -= 8;
}
startQuad = (*buf == '.');
buf++;
}
return ret;
}
int Broadcast::BroadcastToAllInterfaces()
{
DEBUG_LOG(1,"Start Broadcast To All Interfaces", "DEv1");
globalDatabase->SetInBroadcast();
moreThenOne = 0;
#if defined(USE_GETIFADDRS)
struct ifaddrs * ifap;
if (getifaddrs(&ifap) == 0)
{
struct ifaddrs * p = ifap;
while (p)
{
uint32 ifaAddr = SockAddrToUint32(p->ifa_addr);
uint32 maskAddr = SockAddrToUint32(p->ifa_netmask);
uint32 dstAddr = SockAddrToUint32(p->ifa_dstaddr);
if (ifaAddr > 0)
{
char ifaAddrStr[32]; Inet_NtoA(ifaAddr, ifaAddrStr);
char maskAddrStr[32]; Inet_NtoA(maskAddr, maskAddrStr);
char dstAddrStr[32]; Inet_NtoA(dstAddr, dstAddrStr);
std::stringstream addr, descss;
std::string addrs, descs;
addr << dstAddrStr;
descss << p->ifa_name;
descss >> descs;
addr >> addrs;
DoABroadcast(dstAddr);
}
p = p->ifa_next;
}
freeifaddrs(ifap);
}
#elif defined(WIN32)
// Windows XP style implementation
// Adapted from example code at http://msdn2.microsoft.com/en-us/library/aa365917.aspx
// Now get Windows' IPv4 addresses table. Once again, we gotta call GetIpAddrTable()
// multiple times in order to deal with potential race conditions properly.
MIB_IPADDRTABLE * ipTable = NULL;
{
ULONG bufLen = 0;
for (int i = 0; i<5; i++)
{
DWORD ipRet = GetIpAddrTable(ipTable, &bufLen, false);
if (ipRet == ERROR_INSUFFICIENT_BUFFER)
{
free(ipTable); // in case we had previously allocated it STILL_RUN
ipTable = (MIB_IPADDRTABLE *)malloc(bufLen);
}
else if (ipRet == NO_ERROR) break;
else
{
free(ipTable);
ipTable = NULL;
break;
}
}
}
if (ipTable)
{
IP_ADAPTER_INFO * pAdapterInfo = NULL;
{
ULONG bufLen = 0;
for (int i = 0; i<5; i++)
{
DWORD apRet = GetAdaptersInfo(pAdapterInfo, &bufLen);
if (apRet == ERROR_BUFFER_OVERFLOW)
{
free(pAdapterInfo); // in case we had previously allocated it
pAdapterInfo = (IP_ADAPTER_INFO *)malloc(bufLen);
}
else if (apRet == ERROR_SUCCESS) break;
else
{
free(pAdapterInfo);
pAdapterInfo = NULL;
break;
}
}
}
for (DWORD i = 0; i<ipTable->dwNumEntries; i++)
{
const MIB_IPADDRROW & row = ipTable->table[i];
// Now lookup the appropriate adaptor-name in the pAdaptorInfos, if we can find it
const char * name = NULL;
const char * desc = NULL;
if (pAdapterInfo)
{
IP_ADAPTER_INFO * next = pAdapterInfo;
while ((next) && (name == NULL))
{
IP_ADDR_STRING * ipAddr = &next->IpAddressList;
while (ipAddr)
{
if (Inet_AtoN(ipAddr->IpAddress.String) == ntohl(row.dwAddr))
{
name = next->AdapterName;
desc = next->Description;
break;
}
ipAddr = ipAddr->Next;
}
next = next->Next;
}
}
char buf[128];
int setUnnamed = 0;
if (name == NULL)
{
sprintf(buf, "unnamed");
name = buf;
setUnnamed = 1;
}
uint32 ipAddr = ntohl(row.dwAddr);
uint32 netmask = ntohl(row.dwMask);
uint32 baddr = ipAddr & netmask;
if (row.dwBCastAddr) baddr |= ~netmask;
char ifaAddrStr[32]; Inet_NtoA(ipAddr, ifaAddrStr);
char maskAddrStr[32]; Inet_NtoA(netmask, maskAddrStr);
char dstAddrStr[32]; Inet_NtoA(baddr, dstAddrStr);
std::stringstream addr, descss;
std::string addrs, descs;
if (setUnnamed == 0)
{
addr << dstAddrStr;
descss << desc;
descss >> descs;
addr >> addrs;
DoABroadcast(baddr);
}
}
free(pAdapterInfo);
free(ipTable);
}
#else
// Dunno what we're running on here!
# error "Don't know how to implement PrintNetworkInterfaceInfos() on this OS!"
#endif
globalDatabase->SetLeaveBroadcast();
return 1;
}
int Broadcast::DoABroadcast(uint32 broadAddr)
{
int askSinlen = sizeof(struct sockaddr_in);
int askBuflen = MAXBUF;
int message;
char buf[512];
int status;
char askBuffer[MAXBUF];
struct sockaddr_in sock_in, client_adress, client_adress2;
#ifdef __APPLE__
socklen_t clientLength;
int askYes = 1;
#else
char askYes = 1;
int clientLength;
WSADATA w;
int result = WSAStartup(MAKEWORD(2, 2), &w);
#endif
int recSocket = socket(AF_INET, SOCK_DGRAM, 0);
if (recSocket <0)
{
#ifdef __APPLE__
close(recSocket);
#else
closesocket(recSocket);
#endif
inBroadcast = false;
return 10;
}
sock_in.sin_addr.s_addr = htonl(INADDR_ANY);
sock_in.sin_port = htons(4028);
sock_in.sin_family = PF_INET;
client_adress.sin_family = PF_INET;
client_adress.sin_port = htons(4029);
client_adress.sin_addr.s_addr = htonl(broadAddr);
askSinlen = sizeof(sock_in);
client_adress2.sin_family = AF_INET;
client_adress2.sin_port = htons(4028);
client_adress2.sin_addr.s_addr = htonl(0xc0a8b2ff);
status = setsockopt(recSocket, SOL_SOCKET, SO_BROADCAST, &askYes, sizeof(askYes));
if (status < 0)
{
#ifdef __APPLE__
close(recSocket);
#else
closesocket(recSocket);
#endif
inBroadcast = false;
return 10;
}
status = bind(recSocket, (struct sockaddr *)&sock_in, askSinlen);
if (status < 0)
{
#ifdef __APPLE__
close(recSocket);
#else
closesocket(recSocket);
#endif
inBroadcast = false;
return 10;
}
askBuflen = sprintf(askBuffer, "Ciao Mac ist hier");
status = sendto(recSocket, askBuffer, askBuflen, 0, (struct sockaddr *)&client_adress, sizeof(client_adress));
fd_set fds;
struct timeval tv;
tv.tv_sec = 2;
tv.tv_usec = 0;
FD_ZERO(&fds);
FD_SET(recSocket, &fds);
int ret;
if ((ret = select(recSocket +1, &fds, NULL, NULL, &tv)) > 0)
{
int e = 0;
while ((ret = select(recSocket + 1, &fds, NULL, NULL, &tv)) > 0)
{
clientLength = sizeof(client_adress2);
message = recvfrom(recSocket, buf, sizeof(buf), 0, (struct sockaddr*) &client_adress2, &clientLength);
if (message == -1)
{
#ifdef __APPLE__
close(recSocket);
#else
closesocket(recSocket);
#endif
inBroadcast = false;
return -5;
}
else
{
std::string hereisyourbroadcast(buf);
}
}
}
else
{
#ifdef __APPLE__
close(recSocket);
#else
closesocket(recSocket);
#endif
inBroadcast = false;
return -6;
}
#ifdef __APPLE__
close(recSocket);
#else
closesocket(recSocket);
#endif
inBroadcast = false;
return 1;
}

Resources