My knowledge / experience of C is quite limited but I'm trying to create a node addon that uses a node buffer with a C call which expects the buffer to be of type 'unsigned char*' but from what I can see the node buffer Data method provides a 'char*' so the types are incompatible. E.g.
This is how it would be called using c:
int length = 100;
unsigned char buf[length];
int ret = ftdi_read_data(&ftdic, buf, length);
And from what I have read, to use a node buffer you do the following instead:
int length = 100;
node::Buffer *slowBuffer = node::Buffer::New(length);
int ret = ftdi_read_data(&ftdic, node::Buffer::Data(slowBuffer), length);
However this returns the following error when building:
error: invalid conversion from ‘char*’ to ‘unsigned char*’ [-fpermissive]
int ret = ftdi_read_data(&ftdic, node::Buffer::Data(slowBuffer), length);
Is it possible to create a node buffer of type unsigned chars, or achieve this in some other way?
Thanks
In your addon C code use a cast like this: (unsigned char*)node::Buffer::Data(slowBuffer). This is the usual fix for the specific error shown.
Related
I am trying to build a packet counter with eBPF and XDP. I need a way to keep track of the total number of packets received. Since I'm using XDP I use a BPF_ARRAY and increment it every time a packet is received. The problem is I can't seem to access the stored value using the provided lookup() function.
Here is how I create the BPF_ARRAY.
BPF_ARRAY(counter, u64, 1);
Here is how I try to access and use the stored value. The type of output.avg is u64.
int cindex = 0;
counter.increment(&cindex);
long current_count = counter.lookup(&cindex);
output.avg = current_count;
BPF gives me this warning and fails to compile.
warning: incompatible pointer to integer conversion initializing 'long' with
an expression of type 'u64 *' (aka 'unsigned long long *') [-Wint-conversion]
long current_count = counter.lookup(&cindex);
I figured out how to fix my errors. I'm new to C so the pointers confused me a little bit.
int cindex = 0;
counter.increment(cindex);
unsigned long long *current_count = counter.lookup(&cindex);
if(current_count != NULL){
output.avg = *current_count;
}
I am about to make an encryption of a textstring, using another textstring as a "key" for my encryption. It is basically just a reorganization of the ASCII-characters.
The key is given and is structured in a bad way, requiring some extra programming. The ASCII-characters are listed in this key with one charachter for each line, and the corresponding encrypted characters two indexes away.
This is the example of "key.txt":
A g
B 9
C ü
D (
E z
...continuing for all ASCII-characters. An encryption in my program would therfore result in:
"EDABEDA" -> "z(g9z(g"
When I am doing the encryption.
I let the program take in an input-string and I create another string with the encryption-key-characters.
I go through each character in the input string with a for-sling. For each character in the input string, I check if there is a matching character in my encryption-key string. In the encryption key I jump 4 steps at a time since I am going to encrypt and only have to compare A,B,C,D...
I use strcmp() to find a match. And when there is a match, when the character in the input string is the same as in the encryption key, I write the encrypted character to the output string. The encrypted character is placed two indexes ahead of the main character in the key-string.
The warnings occur in the strcmp()
Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 3000
void encryption(char *input);
int main()
{
char input[] = "EDABEDA";
encryption(input);
}
void encryption(char *input)
{
int length,i,k;
size_t result;
char dicc[1000];
char output[SIZE];
FILE *f;
f = fopen("key.txt","r");
fseek(f, 0, SEEK_END);
length = ftell(f);
fseek(f, 0, SEEK_SET);
result = fread(dicc, 1, length, f);
int lenDic = strlen(dicc);
int lenInp = strlen(input);
for (i = 0 ; i < lenInp ; i++)
{
for (k = 4 ; k < lenDic ; k = k + 4)
{
if (strcmp(input[i],dicc[k]) == 0)
{
output[i] = dicc[k+2];
printf("%c",output[i]);
}
}
}
fclose(f);
}
I get the below warnings, and the program doesn't work. Anyone who can help me with this strcmp-warning and know how I should rearrange my program in order to meet its requirements?
warning: passing argument 1 of ‘strcmp’ makes pointer from integer without a cast [enabled by default]
if (strcmp(input[i],dicc[k]) == 0)
^
In file included from crypt.c:3:0:
/usr/include/string.h:144:12: note: expected ‘const char *’ but argument is of type ‘char’
extern int strcmp (const char *__s1, const char *__s2)
^
warning: passing argument 2 of ‘strcmp’ makes pointer from integer without a cast [enabled by default]
if (strcmp(input[i],dicc[k]) == 0)
^
In file included from crypt.c:3:0:
/usr/include/string.h:144:12: note: expected ‘const char *’ but argument is of type ‘char’
extern int strcmp (const char *__s1, const char *__s2)
^
Use strcmp() to compare strings, not characters. For your case this
if (input[i] == dicc[k])
should work.
Note that char is just an integer type not a string type, there is no string type in c. And one more thing, write safe code! Check of fopen() succeeded, and if length doesn't exceed 999. Pretty much every thing that can be considered an error.
My goal is to convert a string such as "A1234" to a long with value 1234. My first step was to just convert "1234" to a long, and that works as expected:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
char* test = "1234";
long val = strtol(test,NULL,10);
char output[20];
sprintf(output,"Value: %Ld",val);
printf("%s\r\n",output);
return 0;
}
Now I am having trouble with pointers and trying to ignore the A at the beginning of the string. I have tried char* test = "A1234"; long val = strtol(test[1],NULL,10); however that crashes the program.
How do I set this up properly to get it pointing to the correct spot?
You are almost right. You need to pass a pointer to strtol, though:
long val = strtol(&test[1], NULL, 10);
or
long val = strtol(test + 1, NULL, 10);
Turning on some compiler warning flags would have told you your problem. For example, from clang (even with no special flags added):
example.c:6:23: warning: incompatible integer to pointer conversion passing
'char' to parameter of type 'const char *'; take the address with &
[-Wint-conversion]
long val = strtol(test[1],NULL,10);
^~~~~~~
&
/usr/include/stdlib.h:181:26: note: passing argument to parameter here
long strtol(const char *, char **, int);
^
1 warning generated.
and from GCC:
example.c: In function ‘main’:
example.c:6: warning: passing argument 1 of ‘strtol’ makes pointer from integer
without a cast
Editorial note: I think you can see from these error messages why beginners are often well-advised to use clang rather than GCC.
I have some C code below:
char update[MAX_UPDATE_LEN];
int remoteLen;
char pholder;
pholder = recv(update,connectDescriptor,MAX_UPDATE_LEN,MSG_DONTWAIT); //error
remoteLen = atoi("pholder");
I keep getting the following errors:
client.cpp:849: error: invalid conversion from `char*' to `int'
client.cpp:849: error: initializing argument 1 of `ssize_t recv(int, void*,
size_t, int)'
client.cpp:849: error: invalid conversion from `int' to `void*'
client.cpp:849: error: initializing argument 2 of `ssize_t recv(int, void*,
size_t, int)'
What is causing these errors?
There are several issues with this code:
char update[MAX_UPDATE_LEN];
int remoteLen;
char pholder;
pholder = recv(update,connectDescriptor,MAX_UPDATE_LEN,MSG_DONTWAIT); <-- error here
remoteLen = atoi("pholder");
recv returns an ssize_t which is usually much bigger than a char. So you can't safely store the return code in pholder.
The arguments to recv() are in the wrong order. Here's the declaration: ssize_t recv(int sockfd, void *buf, size_t len, int flags);
atoi is being passed a string which is not a number "pholder". It expects a string like "12345". If ASCII-encoded numerals is what you expect, you can give update to atoi.
Bonus: use sizeof(update) instead of MAX_UPDATE_LEN for len -- that way if the type declaration or size of update changes, you should still get the expected value.
Here's how you might fix it:
char update[MAX_UPDATE_LEN];
const int flags = MSG_DONTWAIT;
const ssize_t ret = recv(connectDescriptor, update , sizeof(update), flags);
if (-1 == ret)
{
perror("recv");
exit(1);
}
const int remoteLen = strtol(update, update + sizeof(update), 0);
I have been working on getting the sha1() function working from openssl/sha.h however I am getting random output and some warning. I have read quite a bit and tried some of the example codes but I get warning on all of it and it doesn't display correctly.
Here is code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <openssl/sha.h>
int main()
{
const unsigned char data[] = "Hello, World";
unsigned long length = sizeof(data);
unsigned char hash[SHA_DIGEST_LENGTH];
SHA1(data, length, hash);
printf("%02x \n", hash);
return 0;
}
Below is the warning I am getting:
sha.c: In function ‘main’:
sha.c:12: warning: ‘SHA1’ is deprecated (declared at /usr/include/openssl/sha.h:124)
sha.c:13: warning: format ‘%02x’ expects type ‘unsigned int’, but argument 2 has type ‘unsigned char *’
sha.c:13: warning: format ‘%02x’ expects type ‘unsigned int’, but argument 2 has type ‘unsigned char *’
When I run it and I get the output:
62652b34
Any help would be great!
It also took me a while before I figured it all out. The best way is to use EVP, it provides generic functions for almost everything.
#include <openssl/evp.h>
You need to call this im main before calling you hash function. To initialize your hashes. Otherwise openssl will complain that the algorithm is not available.
OpenSSL_add_all_algorithms();
mode must be "SHA256", "SHA512", "SHA1" as string.
dataToHash is the input, dataSize is the size of the input,
outHashed should already be allocated, the hash will be written there
unsigned int hash(const char *mode, const char* dataToHash, size_t dataSize, unsigned char* outHashed) {
unsigned int md_len = -1;
const EVP_MD *md = EVP_get_digestbyname(mode);
if(NULL != md) {
EVP_MD_CTX mdctx;
EVP_MD_CTX_init(&mdctx);
EVP_DigestInit_ex(&mdctx, md, NULL);
EVP_DigestUpdate(&mdctx, dataToHash, dataSize);
EVP_DigestFinal_ex(&mdctx, outHashed, &md_len);
EVP_MD_CTX_cleanup(&mdctx);
}
return md_len;
}
A use example (this is not tested, I use the above code in a c++ wrapper)
const char *inData = "test data2";
unsigned char outHash[20]; // output is already allocated
hash("SHA1", inData, 10, outHash);
You shouldn't use the SHA1 method directly it is deprecated (your code could blow up with the next version).
If you want to use your version you need to print each char as hex:
int i;
for(i=0; i<SHA_DIGEST_LENGTH; i++) {
printf("%02x", hash[i]);
}
You can't dump the entire buffer that way. you need to loop it, such as below. The value you're getting for your output is actually the address of the hash buffer, which is clearly not what you're looking for. You want the hex-bytes in the buffer dumped as text
So...
int main()
{
const unsigned char data[] = "Hello, World";
unsigned long length = sizeof(data);
unsigned char hash[SHA_DIGEST_LENGTH];
SHA1(data, length, hash);
int i=0;
for (;i< sizeof(hash)/sizeof(hash[0]);++i)
printf("%02x \n", hash[i]);
return 0;
}
Regarding your warnings, the deprecation is because this interface is out-dated for performing the crypto-op you're attempting (SHA1). There are newer interfaces in OpenSSL that are current. Consider the EVP interface specifically.
printf("%02u \n", hash);
Remove warnings by printing unsigned char