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).
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.
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;
}
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;
}
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))