Mbed Cortex-m hardfault when sending data via TCP - tcp

I have a TCPSocket* object which holds a connection to a client. This object is passed to another object to send data back to the client:
uint32_t count = 10;
char* message = new char[4];
message[0] = count & 0xff;
message[1] = (count >> 8) & 0xff;
message[2] = (count >> 16) & 0xff;
message[3] = (count >> 24) & 0xff;
client->send(&message, 4);
When this part of the program is called, the following appears on the serial line, and no data is received by the client:
++ MbedOS Fault Handler ++
FaultType: HardFault
Context:
R0 : 00000000
R1 : 10008000
R2 : 00000004
R3 : 2007C000
R4 : 10000914
R5 : 00000000
R6 : 00000000
R7 : 10004330
R8 : 10004320
R9 : FFFFF435
R10 : 00000000
R11 : 00000000
R12 : 00012AC1
SP : 10002AF0
LR : 0000D1A1
PC : 00005938
xPSR : 21000000
PSP : 10002AD0
MSP : 10007FD8
CPUID: 412FC230
HFSR : 40000000
MMFSR: 00000000
BFSR : 00000082
UFSR : 00000000
DFSR : 0000000A
AFSR : 00000000
BFAR : 10008010
Mode : Thread
Priv : Privileged
Stack: PSP
-- MbedOS Fault Handler --
++ MbedOS Error Info ++
Error Status: 0x80FF013D Code: 317 Module: 255
Error Message: Fault exception
Location: 0xD337
Error Value: 0x5938
Current Thread: main Id: 0x10002B48 Entry: 0xD7D7 StackSize: 0x1000 StackMem: 0x10001B48 SP: 0x10007F88
For more info, visit: https://armmbed.github.io/mbedos-error/?error=0x80FF013D
-- MbedOS Error Info --
Everything is in one thread so I cant see what could be causing this.
These are the relevant parts of the program:
main:
// Network interface
EthernetInterface net;
TCPSocket listener; //listens for incoming connection requests
TCPSocket* client;
CommandProcessor commandProcessor(client);
int main() {
int remaining;
int rcount;
char *p;
char *buffer = new char[16];
nsapi_size_or_error_t result;
int n = net.set_network("192.168.1.103","255.255.255.0","192.168.1.2");
pc.printf("\n Success? %d\n", n);
net.connect();
listener.open(&net);
listener.bind(3045);
listener.listen(1);
client = listener.accept(NULL);
client->set_timeout(1000);
led1 = 1;
while(1) {
int remaining = 16;
int rcount = 0;
p = buffer;
while (remaining > 0 && 0 < (result = client->recv(p, remaining))) {
p += result;
rcount += result;
remaining -= result;
}
if (remaining == 0) //full message received
{
commandProcessor.process(buffer);
}
}
}
CommandProcessor:
CommandProcessor::CommandProcessor(TCPSocket* client)
{
this->client = client;
}
void CommandProcessor::process(char* message)
{
switch(message[0]) { //Command is first byte of message
case 0x3: {
uint32_t count = 10 ;
char* message = new char[4];
message[0] = count & 0xff;
message[1] = (count >> 8) & 0xff;
message[2] = (count >> 16) & 0xff;
message[3] = (count >> 24) & 0xff;
client->send(message, 4);
}
}
}

commandProcessor's client is NULL when you call commandProcessor.process(buffer).
Why don’t you create an instance of CommandProcessor after you get a pointer to a socket from accept().
CommandProcessor* commandProcessor;
client = listener.accept(NULL);
commandProcessor = new CommandProcessor(client);
commandProcessor->process(buffer);
Alternatively, you can set client with a function like this.
void CommandProcessor::setClient(TCPSocket* client) {
this->client = client;
}
usage:
client = listener.accept(NULL);
commandProcessor.setClient(client);

Related

Why nghttp2_session_mem_recv does not call any callback? (language: C, library: nghttp2)

ssize_t readlen;
struct evbuffer *input = bufferevent_get_input(bev);
size_t datalen = evbuffer_get_length(input);
unsigned char *data = evbuffer_pullup(input, -1);
readlen = nghttp2_session_mem_recv(session, data, datalen);
if (readlen < 0) {
printf("Fatal error: %s\n", nghttp2_strerror((int)readlen));
return;
}
if (evbuffer_drain(input, (size_t)readlen) != 0) {
printf("Fatal error: evbuffer_drain failed\n");
return;
}
nghttp2_session_mem_recv function does not call any callback even though it has all the callbacks set and the result returned by it is a valid one (return 130 and datalen is also 130).

Permission Denied error message when running this ebpf code

I am getting this error when running xdp.py file
bpf: Failed to load program: Permission denied
; int dropper(struct xdp_md *ctx) {
0: (b7) r6 = 2
; void *data_end = (void *)(long)ctx->data_end;
1: (61) r2 = *(u32 *)(r1 +4)
; void *data = (void *)(long)ctx->data;
2: (61) r1 = *(u32 *)(r1 +0)
; if (data + ipsize > data_end) {
3: (bf) r3 = r1
4: (07) r3 += 34
; if (data + ipsize > data_end) {
5: (2d) if r3 > r2 goto pc+21
R1_w=pkt(id=0,off=0,r=34,imm=0) R2_w=pkt_end(id=0,off=0,imm=0) R3_w=pkt(id=0,off=34,r=34,imm=0) R6_w=inv2 R10=fp0
; if (ip->protocol == IPPROTO_TCP) {
6: (71) r2 = *(u8 *)(r1 +23)
; if (ip->protocol == IPPROTO_TCP) {
7: (55) if r2 != 0x6 goto pc+19
R1_w=pkt(id=0,off=0,r=34,imm=0) R2_w=inv6 R3_w=pkt(id=0,off=34,r=34,imm=0) R6_w=inv2 R10=fp0
8: (b7) r6 = 1
; if (ntohs(tcp->dest) == 4040){
9: (69) r1 = *(u16 *)(r1 +96)
invalid access to packet, off=96 size=2, R1(id=0,off=96,r=34)
R1 offset is outside of the packet
processed 10 insns (limit 1000000) max_states_per_insn 0 total_states 0 peak_states 0 mark_read 0
Traceback (most recent call last):
File "/home/kali/Documents/assignment/xdp.py", line 6, in <module>
fn = b.load_func("dropper", BPF.XDP)
File "/usr/lib/python3/dist-packages/bcc/__init__.py", line 527, in load_func
raise Exception("Failed to load BPF program %s: %s" %
Exception: Failed to load BPF program b'dropper': Permission denied
This is my xdp.py code
from bcc import BPF #1
from bcc.utils import printb
device = "lo"
b = BPF(src_file="dropper.c")
fn = b.load_func("dropper", BPF.XDP)
b.attach_xdp(device, fn, 0)
b.trace_print()
b.remove_xdp(device, 0)
This is my dropper.c code
#include <linux/bpf.h>
#include <linux/in.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/pkt_cls.h>
#include <linux/tcp.h>
#define SEC(NAME) __attribute__((section(NAME), used))
#undef ntohs
#define ntohs(val) ((val)&0x00ff <<8 | (val)&0xff00 >>8)
SEC("dropper_main")
int dropper(struct xdp_md *ctx) {
int ipsize = 0;
void *data = (void *)(long)ctx->data;
void *data_end = (void *)(long)ctx->data_end;
struct ethhdr *eth = data;
ipsize = sizeof(*eth);
struct iphdr *ip = data + ipsize;
ipsize += sizeof(struct iphdr);
if (data + ipsize > data_end) {
return XDP_PASS;
}
if (ip->protocol == IPPROTO_TCP) {
struct tcphdr *tcp = (struct tcphdr *)((__u32 *)ip + sizeof(*ip));
//bpf_trace_printk("Packet dropped");
if (ntohs(tcp->dest) == 4040){
bpf_trace_printk("Packet dropped at 4040");
}
return XDP_DROP;
}
return XDP_PASS;
}
I am trying to print Packet Dropped message if a packet falls in Tcp port 4040.
I am able to achieve Packet Dropped message whenever a packet is sent on a Tcp port but not able to achieve result only for port 4040.
You need to check the packet is long enough to have the TCP header before accessing that header, in the same way you checked it was long enough to have the IP header before accessing the protocol field.

Cipher text generated by OpenSSL and Windows CNG is different for AES-128-CFB

I am encrypting the same plain text with AES-128-CFB but ciphertext generated by "Windows Cryptography API: Next Generation" and OpenSSL are different for the same IV, and key.
Plain Text: The quick brown fox jumps over the lazy dog
IV: 1234567887654321
Key: 1234567887654321
Cipher Text generated by Windows CNG in Hex: 279CB0C2FD67B37F33A861CDDAFBEDCEEAEFC68FD5B3478E67E4A936BA7CFE75DDBAD370A1E4D6CDC3455E2F4E188A9C
Cipher Text length generated by Windows CNG: 48 Bytes
Cipher Text generated by OpenSSL in Hex: 279CB0C2FD67B37F33A861CDDAFBEDCEEAEFC68FD5B3478E67E4A936BA7CFE75DDBAD370A1E4D6CDC3455E
Cipher Text length generated by Windows CNG: 43 Bytes
Windows CNG adding extra 5 bytes(2F4E188A9C) at the end, I thought it is due to padding and sent dwFlags value as 0 instead of BCRYPT_BLOCK_PADDING then BCryptEncrypt API call failing with error code 0xc0000206/STATUS_INVALID_BUFFER_SIZE.
Windows CNG code:
#include <windows.h>
#include <stdio.h>
#include <bcrypt.h>
#pragma comment(lib, "bcrypt.lib")
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
#define STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L)
void
hexdump(const char *msg, const unsigned char *in, unsigned int len)
{
printf("%s [%d][", msg, len);
for (; len > 0; len--, in++) {
printf("%02X", *in);
}
printf("]\n");
}
const BYTE rgbPlaintext[] = "The quick brown fox jumps over the lazy dog";
static const BYTE rgbIV[] = "1234567887654321";
static const BYTE rgbAES128Key[] = "0123456789abcdefghijklmnopqrstuv";
const int ival_len = 16;
const int key_len = 16;
const DWORD block_len = 16;
void __cdecl wmain(
int argc,
__in_ecount(argc) LPWSTR *wargv)
{
BCRYPT_ALG_HANDLE hAesAlg = NULL;
BCRYPT_KEY_HANDLE hKey = NULL;
NTSTATUS status = STATUS_UNSUCCESSFUL;
DWORD cbCipherText = 0,
cbData = 0,
cbKeyObject = 0,
cbBlockLen = 0,
cbBlob = 0;
PBYTE pbCipherText = NULL,
pbKeyObject = NULL,
pbIV = NULL,
pbBlob = NULL;
UNREFERENCED_PARAMETER(argc);
UNREFERENCED_PARAMETER(wargv);
if(!NT_SUCCESS(status = BCryptOpenAlgorithmProvider(
&hAesAlg,
BCRYPT_AES_ALGORITHM,
NULL,
0)))
{
wprintf(L"**** Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status);
goto Cleanup;
}
if(!NT_SUCCESS(status = BCryptGetProperty(
hAesAlg,
BCRYPT_OBJECT_LENGTH,
(PBYTE)&cbKeyObject,
sizeof(DWORD),
&cbData,
0)))
{
wprintf(L"**** Error 0x%x returned by BCryptGetProperty\n", status);
goto Cleanup;
}
pbKeyObject = (PBYTE)HeapAlloc (GetProcessHeap (), 0, cbKeyObject);
if(NULL == pbKeyObject)
{
wprintf(L"**** memory allocation failed\n");
goto Cleanup;
}
if (ival_len > sizeof (rgbIV))
{
wprintf (L"**** block length is longer than the provided IV length\n");
goto Cleanup;
}
if(ival_len > 0)
{
pbIV= (PBYTE) HeapAlloc (GetProcessHeap (), 0, ival_len + 1);
if(NULL == pbIV)
{
wprintf(L"**** memory allocation failed\n");
goto Cleanup;
}
strncpy(pbIV,rgbIV,ival_len);
pbIV[ival_len]='\0';
}
if(!NT_SUCCESS(status = BCryptSetProperty(
hAesAlg,
BCRYPT_CHAINING_MODE,
(PBYTE)BCRYPT_CHAIN_MODE_CFB,
sizeof(BCRYPT_CHAIN_MODE_CFB),
0)))
{
wprintf(L"**** Error 0x%x returned by BCryptSetProperty\n", status);
goto Cleanup;
}
if(!NT_SUCCESS(status = BCryptGetProperty(
hAesAlg,
BCRYPT_BLOCK_LENGTH,
(PBYTE)&cbBlockLen,
sizeof(DWORD),
&cbData,
0)))
{
wprintf(L"**** Error 0x%x returned by BCryptGetProperty\n", status);
goto Cleanup;
}
if(!NT_SUCCESS(status = BCryptGenerateSymmetricKey(
hAesAlg,
&hKey,
pbKeyObject,
cbKeyObject,
(PBYTE)rgbAES128Key,
key_len,
0)))
{
wprintf(L"**** Error 0x%x returned by BCryptGenerateSymmetricKey\n ", status);
fprintf(stderr, "\nError number <%x>", GetLastError());
goto Cleanup;
}
if (!NT_SUCCESS(status = BCryptSetProperty(hKey,
BCRYPT_MESSAGE_BLOCK_LENGTH,
(PBYTE)&block_len,
sizeof(DWORD),
0))) {
wprintf(L"**** Error 0x%x returned by BCryptSetProperty\n ", status);
fprintf(stderr, "\nError number <%x>", GetLastError());
goto Cleanup;
}
printf("\nplan text is [%d][%s]\n", sizeof(rgbPlaintext) - 1, rgbPlaintext);
if(!NT_SUCCESS(status = BCryptEncrypt(
hKey,
rgbPlaintext,
sizeof(rgbPlaintext) - 1,
NULL,
pbIV,
ival_len,
NULL,
0,
&cbCipherText,
BCRYPT_BLOCK_PADDING)))
{
wprintf(L"\n**** Error 1 0x%x returned by BCryptEncrypt\n", status);
goto Cleanup;
}
pbCipherText = (PBYTE)HeapAlloc (GetProcessHeap (), 0, cbCipherText);
if(NULL == pbCipherText)
{
wprintf(L"**** memory allocation failed\n");
goto Cleanup;
}
// Use the key to encrypt the plaintext buffer.
// For block sized messages, block padding will add an extra block.
if(!NT_SUCCESS(status = BCryptEncrypt(
hKey,
rgbPlaintext,
sizeof(rgbPlaintext) - 1,
NULL,
pbIV,
ival_len,
pbCipherText,
cbCipherText,
&cbData,
BCRYPT_BLOCK_PADDING)))
{
wprintf(L"**** Error 2 0x%x returned by BCryptEncrypt\n", status);
goto Cleanup;
}
hexdump("cipher is", pbCipherText, cbCipherText);
Cleanup:
if(hAesAlg)
{
BCryptCloseAlgorithmProvider(hAesAlg,0);
}
if (hKey)
{
BCryptDestroyKey(hKey);
}
if(pbCipherText)
{
HeapFree(GetProcessHeap(), 0, pbCipherText);
}
if(pbKeyObject)
{
HeapFree(GetProcessHeap(), 0, pbKeyObject);
}
if(pbIV)
{
HeapFree(GetProcessHeap(), 0, pbIV);
}
}
OpenSSL Code:
#include <openssl/conf.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <string.h>
void
hexdump(const char *msg, const unsigned char *in, unsigned int len)
{
printf("%s [%d][", msg, len);
for (; len > 0; len--, in++) {
printf("%02X", *in);
}
printf("]\n");
}
int main(void)
{
/* A 256 bit key */
unsigned char *key = (unsigned char *)"0123456789abcdefghijklmnopqrstuv";
/* A 128 bit IV */
unsigned char *iv = (unsigned char *)"1234567887654321";
/* Message to be encrypted */
unsigned char *plaintext =
(unsigned char *)"The quick brown fox jumps over the lazy dog12312";
unsigned char ciphertext[128];
int ciphertextLen = encrypt(plaintext, strlen ((char *)plaintext), key, iv, ciphertext);
hexdump("cipher value is:", ciphertext, ciphertextLen);
return 0;
}
void handleErrors(void)
{
ERR_print_errors_fp(stderr);
abort();
}
int encrypt(unsigned char *plaintext,
int plaintext_len,
unsigned char *key,
unsigned char *iv,
unsigned char *ciphertext)
{
EVP_CIPHER_CTX *ctx;
int len;
int ciphertextLen;
/* Create and initialise the context */
if(!(ctx = EVP_CIPHER_CTX_new()))
handleErrors();
if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_128_cfb(), NULL, key, iv))
handleErrors();
if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len))
handleErrors();
ciphertextLen = len;
if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len))
handleErrors();
ciphertextLen += len;
EVP_CIPHER_CTX_free(ctx);
return ciphertextLen;
}

Find source address from multicast message in esp8266?

I'm using non-OS SDK v2.0 for esp8266.
I join a multicast group.
I then receive a message (that was sent to multicast).
I want to respond to the sender, but in struct espconn, udp.remote_ip is the address of the multicast group, not sender.
How do I get the ip address of the sender?
Edit:
Receive function has an void* arg argument that is casted to struct espconn.
The old method doesn't do the job anymore, but I found a way to find remote ip and port.
New code:
struct espconn* udp_ch;
remot_info *premot = NULL;
udp_ch = arg;
if (espconn_get_connection_info(udp_ch,&premot,0) == ESPCONN_OK){
os_printf("%d.%d.%d.%d:%d\n", premot->remote_ip[0], premot->remote_ip[1], premot->remote_ip[2], premot->remote_ip[3], premot->remote_port);
}
else{
os_printf("Get info fail\n");
}
This is exactly what I was searching for before. For now, as far as I can see, it works well.
OLD:
I found a way to find the ip, but I don't think it should be done this way. Until I find better, I will use this.
The first thing I did was print first 256 hex values, from void* arg.
I noticed that my address was occurring before a bunch of zeros.
On unicast, the starting position of 0s was 128.
I'm currently using this function:
uint32_t udp_get_addr(void* arg){
uint32_t adr = 0;
uint16_t pos;
uint8_t* data = (uint8_t*) arg;
//unicast?
for(pos = 128; pos<144; pos++){
if(data[pos] != 0){
adr = 1;
break;
}
}
//multicast
if(adr == 1)
pos = 172;
else
pos = 124;
adr = data[pos]<<24 | data[pos+1]<<16 | data[pos+2]<<8 | data[pos+3];
return adr;
}
I know this method is bad, and there is a number of things that can be changed for the better, but for now, this will do.
Edit2:
I needed the source port also. It is located 4 bytes before address. New functions that I currently use:
#define SRC_ADDR_U 120
#define SRC_ADDR_M 168
uint32_t udp_src_addr(void* arg, uint8_t isMulticast){
uint32_t res;
uint8_t* tmp = (uint8_t*) arg;
uint16_t pos;
if(isMulticast) pos = SRC_ADDR_M+4;
else pos = SRC_ADDR_U+4;
res = (tmp[pos+3] << 24) | (tmp[pos+2] << 16) | (tmp[pos+1] << 8) | tmp[pos];
return res;
}
uint16_t udp_src_port(void* arg, uint8_t isMulticast){
uint32_t res;
uint8_t* tmp = (uint8_t*) arg;
uint16_t pos;
if(isMulticast) pos = SRC_ADDR_M;
else pos = SRC_ADDR_U;
res = (tmp[pos+1] << 8) | tmp[pos];
return res;
}

Why does serial communication only work in one direction (chip->PC) with my code?

I am writing code for an Arduino Mega 2560 in C and I am trying to do bidirectional communication over the serial port. However, only sending data from the Arduino to the PC works - the other way doesn't. The RX LED on the arduino shortly lights up, but my code doesn't receive the data (the LED connected to "pin 13" doesn't light up). Does anyone know how to fix this?
Here's the code that's running on the arduino:
#define USART_BAUDRATE 500000
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)
static void serial_init(void) {
// load upper 8 bits of the baud rate into the high byte of the UBRR register
UBRR0H = (BAUD_PRESCALE >> 8);
// load lower 8 bits of the baud rate into the low byte of the UBRR register
UBRR0L = BAUD_PRESCALE;
// 8data,1stopbit
UCSR0C = (0 << UMSEL00) | (1 << UCSZ00) | (1 << UCSZ01);
// turn on the transmission and reception circuitry
UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (0 << UCSZ02);
}
static void sendbyte(uint8_t b) {
// do nothing until UDR is ready for more data to be written to it
while ((UCSR0A & (1 << UDRE0)) == 0) {};
// memory was cleared - write to it
UDR0 = b;
}
static void digi_init() {
// configure port B7 (arduino digital port 13) as output and set it low
PORTB = (0<<PB7);
DDRB = (1<<DDB7);
}
static void digi_set(int val) {
PORTB = (val<<PB7);
}
int main(void) {
serial_init();
digi_init();
while (1) {
if ((UCSR0A & (1 << RXC0)) == 1) {
// we got some data, light up the LED!
digi_set(1);
}
_delay_ms(50);
sendbyte('.');
}
}
And here's the code that's running on the PC:
int main(int argc, char *argv[]) {
char *serialdevicepath = "/dev/ttyACM0";
fprintf(stderr, "Connecting to serial device ...\n");
int serial_fd = open(serialdevicepath, O_RDWR | O_NOCTTY);
struct termios config;
if(tcgetattr(serial_fd, &config) < 0) exit(1);
config.c_iflag &= ~(IGNBRK | BRKINT | ICRNL | INLCR | PARMRK | INPCK | ISTRIP | IXON);
config.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN | ISIG);
config.c_cflag &= ~(CSIZE | PARENB);
config.c_cflag |= CS8;
config.c_cc[VMIN] = 1;
config.c_cc[VTIME] = 0;
if(cfsetispeed(&config, B500000) < 0 || cfsetospeed(&config, B500000) < 0) exit(1);
if(tcsetattr(serial_fd, TCSAFLUSH, &config) < 0) exit(1);
FILE *serial = fdopen(serial_fd, "r");
setbuf(stdin, NULL);
fcntl(0/*stdin*/, F_SETFL, O_NONBLOCK);
setbuf(stdout, NULL);
setbuf(stderr, NULL);
setbuf(serial, NULL);
while (1) {
char c;
while (read(0, &c, 1) == 1) {
if (c != '+' && c != '-') continue;
uint8_t val = (c == '+') ? 42 : 41;
if (write(serial_fd, &val, 1) != 1) {
assert(0);
}
}
char b = fgetc(serial))&0xe0);
fprintf(stderr, "read 0x%x\n", b);
}
return 0;
}
(And yes, I am typing <+> on the PC so that it does send data. Also, I tried turning on the LED from the code directly and it worked.)
if ((UCSR0A & (1 << RXC0)) == 1)
That test is wrong, it will never be 1. The & operator here will produce either 0 or (1 << RXC0). Favor it this way instead:
if ((UCSR0A & (1 << RXC0)) != 0)
Or in C you'd typically write it this way since any non-zero value is logically true:
if (UCSR0A & (1 << RXC0))

Resources