I am using following api to initialize sockfd at client side:(sockfd=3)
if ((sockfd = socket(p->ai_family, p->ai_socktype,p->ai_protocol)) == -1) {
perror("client: socket");
continue;
}
& initializing my TPKT_Buff to {3,0,0,0} value by using function :
if(Fill_TPKT(PStack,TPKT_Buff) != 0)
{
printf("Error while filling TPKT Buffer");
return 1;
}printf("tpkt/2_Buff%x %x\n",TPKT_Buff[0],TPKT_Buff[1]);printf("sockfd=%d\n",sockfd);
But, after calling function :
if(Fill_COTP(PStack,&cotp) != 0)
{
printf("Error while filling COTP Structure!");
return 1;
}
my socfd & TPKT_Buff values changed to zero TPKT_Buff={0,0,0,0} & sockfd=0 :
printf("sockfd=%d\n",sockfd);
printf("TPKT/2_Buff=%x %x\n",TPKT_Buff[0],TPKT_Buff[1]);
Definitions of functions Fill_COTP & Fill_TPKT are as follows :
int Fill_TPKT(FILE *fptr,unsigned char *buf)
{
fseek(fptr,14,SEEK_SET);
fscanf(fptr,"%d",buf+0);
fseek(fptr,15,SEEK_CUR);
fscanf(fptr,"%d",buf+1);
return 0;
}
int Fill_COTP(FILE *fptr, COTP *cotp)
{
unsigned short temp;
fseek(fptr,13,SEEK_CUR);
fscanf(fptr,"%d",&temp);
cotp->Destination_Ref[1] = temp;
cotp->Destination_Ref[0] = temp>>8;
printf("%x %x\n",cotp->Destination_Ref[0],cotp->Destination_Ref[1]);
fseek(fptr,13,SEEK_CUR);
fscanf(fptr,"%d",&temp);
cotp->Source_Ref[1] = temp;
cotp->Source_Ref[0] = temp>>8;
printf("%x %x\n",cotp->Source_Ref[0],cotp->Source_Ref[1]);
fseek(fptr,14,SEEK_CUR);
fscanf(fptr,"%d",&temp);
cotp->Source_Tsap[1] = temp;
cotp->Source_Tsap[0] = temp>>8;
printf("%x %x\n",cotp->Source_Tsap[0],cotp->Source_Tsap[1]);
fseek(fptr,14,SEEK_CUR);
fscanf(fptr,"%d",&temp);
cotp->Destination_Tsap[1] = temp;
cotp->Destination_Tsap[0] = temp>>8;
printf("%x %x\n",cotp->Destination_Tsap[0],cotp->Destination_Tsap[1]);
fseek(fptr,17,SEEK_CUR);
fscanf(fptr,"%d",&(cotp->TPDU_size));
printf("%x\n",cotp->TPDU_size);
return 0;
}
Here PStack is a file pointer.
I am not getting why my sockfd & TPKT_Buff values changing to zero even I am not using these values in my function Fill_COTP();
Please give some suggestion.
Definition of COTP is:
typedef struct
{
unsigned char PDU_type;
unsigned char Destination_Ref[2];
unsigned char Source_Ref[2];
unsigned char Source_Tsap[2];
unsigned char Destination_Tsap[2];
unsigned char TPDU_size;
} COTP;
There is no relation between sockfd & TPKT_Buff.
The trouble appears to be in the line:
fscanf(fptr,"%d",&(cotp->TPDU_size));
Your TPCU_size is unsigned char TPDU_size; which is only 1 byte (assuming this to be the size of 'char') in size, but you are trying put 4 bytes (assuming that to be the size of 'int') into it during fscanf, thereby potentially overwriting the memory around it.
While there is some information missing, some of what you have shown is clearly wrong and is likely to be involved in the problem. For instance:
int Fill_TPKT(FILE *fptr,unsigned char *buf)
{
fseek(fptr,14,SEEK_SET);
fscanf(fptr,"%d",buf+0);
fseek(fptr,15,SEEK_CUR);
fscanf(fptr,"%d",buf+1);
If each call to fscanf works, each will fill in one int, but buf points to a sequence of unsigned chars. Unless you have very large chars and sizeof(int) == 1 this is obviously wrong.
The same mistake is repeated at many other points, e.g., in Fill_COTP, fscanf with a %d directive is used to fill in temp, which has type unsigned short rather than int.
You could change the directives (%hhd will fill in a single char and %hd will fill in a single short; %hhu and %hu will fill in unsigned char and unsigned short). However, simply calling fscanf like this, without any error checking, is not very robust. If the contents of the input stream are not convert-able to the target type, the call will fail (fscanf will return either EOF or a short count, depending on the kind of failure, "input" vs "matching", and the point of the failure). You might want a little intermediate function that does appropriate error checking, perhaps scanning into an int after all and then range-checking the value for instance.
Related
So I'm reading from a file descriptor which contains an int variable in its raw byte format.
So I'm doing:
char buffer[sizeof(int)];
ssize_t sizeOfFile = read(sock_fd, buffer, sizeof(int));
int extractedInt = ???;
How can I convert that buffer to an integer? I was thinking of memcpy but was wondering if there are better ways.
You could read directly an integer
int extractedInt;
ssize_t sizeOfFile = read(sock_fd, &extractedInt, sizeof(int));
read will read the size of an int bytes, and store them into extractedInt.
If your int is actually a string in a file you want to convert to an int, the procedure is a bit different.
#define SIZE 20
char buffer[SIZE]; // ensure there is enough space for a string containing an integer
ssize_t sizeOfFile = read(sock_fd, buffer, SIZE);
int extractedInt = atoi(buffer); // convert string to integer
I can guess from your code that you're reading from the network. This is then not portable to just read a int from the buffer, in your network protocol you chose a certain endianness but you cannot expect that all the platforms where your program will run to have the same, so it will lead to bad convertions.
And other proposed solutions of asking read to return an int will lead to the same problem.
So in your case, I can only advice to iterate through your array and compute the integer by progressively placing the bytes at the right place depending on the endianness of the platform.
You can detect the endianness of the build target platform by using the macro __BYTE_ORDER__in GCC.
There is an example for network data that is big endian:
// construct an `int` with the bytes in the given buffer
// considering the buffer contains the representation
// of an int in big endian
int buffer_to_int(char* buffer, int buffer_size) {
int result = 0;
int i;
char sign = buffer[0] & 0x80;
char * res_bytes = (char*)&result; // this pointer allows to access the int bytes
int offset = sizeof(int) - buffer_size;
if( sign != 0 )
sign = 0xFF;
if( offset < 0 ) {
// not representable with a `int` type
// we chose here to return the closest representable value
if( sign == 0 ) { //positive
return INT_MAX;
} else {
return INT_MIN;
}
}
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
for(i=0; i<buffer_size; i++) {
res_bytes[i] = buffer[buffer_size-i-1]; // invert the bytes
}
for(i=0; i<offset; i++){
res_bytes[buffer_size+i] = sign;
}
#else
// same endianness, so simply copy bytes using memcpy
memcpy(&result + offset, buffer, buffer_size);
for(i=0; i<offset; i++){
res_bytes[i] = sign;
}
#endif
return result;
}
int getLineCount() {
int ret = 0;
char c;
while ((c = fgetc(stdin)) != EOF)
if (c == '\n')
ret++;
return ret + 1;
}
void fill(char *WORD) {
int charIndex = 0;
char c;
while ((c = fgetc(stdin)) != EOF) {
*(WORD + charIndex++) = c;
}
}
int main() {
int lineNum = getLineCount();
char *WORD = (char*)calloc(lineNum * 18,sizeof(int));
fill(WORD);
return 0;
}
Here is the part of my code, and my question is(as you can see):
I'm trying to read stdin's content twice, but after the getLineCount function, it stays at the EOF and I can't read it again in fill function.
Im taking stdin from the user with this command in Linux;
$./output < text_file.txt
Is there any way to roll back stdin to starting character? If not, how can I fix this problem?
Thanks.
You can use rewind(stdin) to set the stream back to the start of file, but be aware that it is not guaranteed to work, especially if the stream is a pipe, a terminal or a device.
Your allocation scheme is incorrect: you could compute the size of the file and then allocate that many bytes, but your current (char*)calloc(lineNum * 18,sizeof(int)); allocates 18 times the size of type int for each line. Some files with short lines will fit in this array while others will invoke undefined behavior.
Note that c must be defined as int for c = fgetc(stdin); to properly store all values including the EOF special value.
Don't use rewind.
You can, of course, save the data you read from stdin (potentially in a file if it's too large for main memory) and operate on that.
Another possibility is this:
struct callback {
void (*call) (char, void *);
void * data;
};
void with_characters_from(FILE * file, struct callback const * callbacks, size_t count) {
int c;
while ((c = fgetc(file)) != EOF) {
char character = c & 0xFF;
for (size_t i = 0; i < count; ++i) {
callbacks[i].call(character, callbacks[i].data);
}
}
}
You inverse control, such that no longer your functions are "pulling data out of" stdin, but rather the data (characters) are "pushed to" them. Note that this can lead to callback hell, and in C you sacrifice a good portion of type safety (as well as code clarity .. no first class functions / closures ... sigh).
A small test:
struct counter_data {
char const character;
unsigned count;
};
void counter (char character, void * vptr) {
struct counter_data * data = vptr;
if (character == data->character) {
++(data->count);
}
}
int main() {
struct counter_data data [2] = {
{'a', 0}, {'x', 0}};
struct callback callbacks [2] = {
{&counter, &(data [0])},
{&counter, &(data [1])}};
with_characters_from (stdin, callbacks, 2);
printf("Counted %c %u times \n", data [0].character, data [0].count);
printf("Counted %c %u times \n", data [1].character, data [1].count);
return 0;
}
As already noted, for your particular example, you should consider a completely different approach: If possible compute the required size beforehand. If you exceed that size (which you should always test for), then use realloc in order to get a larger chunk of memory.
The assignment requires that you design a router table lookup routine that will take a destination IP address from a simulated frame (actually the packet within the simulated frame) and then executes a search of a routing table (keep it simple say a 2 x 2 array with one column being the known IP addresses and one being the port in the simulated box where you will direct packets bound for this IP towards).
I've been working on this for awhile and i'm stuck. Can someone help me! I've created a text file and tried to insert it in the the project but it still does not detect it. I don't know what else to do. Thanks in advance!!
#include <stdio.h>
#include "stdlib.h"
#include "string.h"
void Ouccpy_Routing_Table();
typedef struct RTE
{
unsigned long Dest;
int port;
unsigned long Route;
};
Route[120];
struct IP
{
unsigned char Ipverison;
unsigned char TOS;
unsigned short ID;
unsigned short Fragoffset;
unsigned char TTL;
unsigned char Protcl;
unsigned char dcheksum;
unsigned char Data[1];
};
int main()
{
int count;
FILE *ptr_testfile;
struct IP my_testfile;
ptr_testfile = fopen_s("c:\\testroute\\TEST.txt", "rb");
if (!ptr_testfile)
{
printf("Cannot Open File!");
return 1;
}
while (count = 2) count <= (sizeof(struct IP)); count++;
{
fread(&my_testfile, sizeof(struct IP), 2, ptr_testfile);
}
fclose(ptr_testfile);
return 0;
}
void Ouccpy_Routing_Table()
{
}
Put the text file in the corresponsing location.
c:\testroute\TEST.txt
Verify it before compiling. If the problem persists, please post the error code?
Regarding the way the code tries to open the file
ptr_testfile = fopen_s("c:\\testroute\\TEST.txt", "rb");
The compiler should at least warn you not providing enough parameters.
If you would have read the documentation to fread_s() you would have learned that it should have been called:
errno_t en = fopen_s(&ptr_testfile, "c:\\testroute\\TEST.txt", "rb");
if (0 != en)
{
issue some error message here
}
As an alternative you could use the standard fopen() instead the Microsoft specific fopen_s(). fopen() would be called as your original code does.
This
while (count = 2) count <= (sizeof(struct IP)); count++;
{
fread(...);
}
is the same as
while (count = 2)
count <= (sizeof(struct IP));
count++;
{
fread(...);
}
which in turn is the same as
while (count = 2) /* This repeatly assigns 2 to count. Resulting in an infinite loop.*/
{
count <= sizeof(struct IP); /* This does nothing. */
}
/* Because of the infinite loop above the code never arrives here. */
count++;
fread(...);
Please have a second look.
I have a network capture tool that captures packets and does some processing on them. Now, here is a small fragment of the code. u_char is the name given to unsigned char. When I try to print the variable smac to stdout, all I get is 000000000000 on the screen. I want to print the actual smac and dmac.
char * str;
char converted[6*2 + 1];
u_char smac[6], dmac[6];
int i;
if (ntop_lua_check(vm, __FUNCTION__, id, LUA_TSTRING))
return(CONST_LUA_PARAM_ERROR);
if ((str = (char*)lua_tostring(vm, id)) == NULL)
return(CONST_LUA_PARAM_ERROR);
sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
&smac[0], &smac[1], &smac[2], &smac[3], &smac[4], &smac[5]);
for (i = 0; i < 6; i++)
{
sprintf(&converted[i*2], "%02X", smac[i]);
}
printf("%s\n", converted);
Is the problem with unsigned char getting promoted to int or something by sprintf and printing the unnecessary two bytes? I am not sure.Any help would be of great value. Thank you.
Firstly, i'm not very familiarized with C, i come from Java, C#, C++... and possibly i inherited defects from this languages in order to realize this practice, well i have the follows question, here is my code:
#include <stdio.h>
#include <stdlib.h>
void decrypt(unsigned long* v, unsigned long* k);
const int MAX = 32;
const long delta = 0x9e3779b9;
long sum=0xC6EF3720;
int main() {
FILE *fp;
FILE *destino;
unsigned long v[2];
unsigned long k[4] = { 128, 129, 130, 131 };
unsigned long tam=0;
char* buffer;
char* aux[sizeof(unsigned long)];
int i;
if ((fp = fopen("image.png", "rb")) == NULL) {
printf ("Error! \n ");
return 0;
}
else {
fread(&aux,sizeof(unsigned long),1,fp);
memcpy(&tam,&aux,sizeof(unsigned long));
buffer = (char*)malloc(tam);
//fread(&buffer,1,tam,fp);
char *buffer2[28568];
fread(&buffer2,1,28568,fp);
/*for(i = 0;i < tam;++i) {
printf("%c", ((char *)buffer2)[i]);
}*/
for(i=4;i<tam;i+=8) {
memcpy(&v,&buffer2[i],8);
decrypt(&v,&k);
}
if ((result= fopen("image2.png", "rb")) == NULL) {
printf ("Error! \n ");
return 0;
}
else {
fwrite(v,sizeof(unsigned long)*2,1,result);
fclose (result);
fclose(fp);
}
}
return 0;
}
void decrypt(unsigned long* v, unsigned long* k) {
int i=0;
while(i<MAX) {
v[1] = v[1] -((4 << v[0])+(k[2]^v[0])+(sum^(5 >> v[0]))+k[3]);
v[0] = v[0] -((4 << v[1])+(k[0]^v[1])+(sum^(5 >> v[1]))+k[1]);
sum = sum-delta;
i++;
}
}
Where tam is the size of my binary file (image in this case) where i store first 4 bytes (unsigned long) where is located the size in my png file (28568)
When i create my char* buffer i have to assign dynamically with malloc but when i make a new fread from my file i get a "No source available for "msvrct!memcpy() at 0xrandom_memory_address" from Eclipse when i debug, well, i comment this line and i try to make it manually set a new buffer2 with 28568 as size of my array, apparently works, making a iteration of buffer2 prints ascii characters values but when i call decrypt for make the decryption of my image, the final result is stored in v array which i have to copy in a new file, i tried to search how to make a empty image png in C but i didn't find anything, so i created a copy of my encrypt image calling it "image2.png" but i suppose this not the "clean solution" for that, because for the other hand is not working at all.
For more explanation about this exercise just say that the decrypt funcion work with blocks of 8 bytes (64 bits) that through a key (array k) make a series of operation where they store in v array itself, crossing through the loop 8 in 8 and retrieve the value of buffer in v in each one, after the loop execution we have the result in v and only left to copy in a new file where finally show up the image decrypt.
It's a very complex practice for all of one newbies in C, it's driving my crazy trying to figure out what i doing wrong.
I hope anyone can see what i'm not able to for now.
I think you are having problems with the declarations of the buffers. I think the correct should be:
FILE *fp;
FILE *destino;
unsigned long v[2];
unsigned long k[4] = { 128, 129, 130, 131 };
unsigned long tam=0;
char* buffer;
char aux[sizeof(unsigned long)]; // without the "*"
int i;
if ((fp = fopen("image.png", "rb")) == NULL) {
printf ("Error! \n ");
return 0;
}
else {
fread(aux,sizeof(unsigned long),1,fp);
memcpy(&tam,aux,sizeof(unsigned long));
buffer = (char*)malloc(tam);
//fread(buffer,1,tam,fp); // without the "&" in this case
char buffer2[28568]; // without the "*"
fread(buffer2,1,28568,fp); // or fread(buffer,1,tam,fp);
/*for(i = 0;i < tam;++i) {
printf("%c", buffer2[i]); // or buufer[i] if you change to use it again
}*/
for(i=4;i<tam;i+=8) {
memcpy(v,&buffer2[i],8);
decrypt(v,k);
}
...
I don't fully understand what you are trying to accomplish, but one problem is here:
char* aux[sizeof(unsigned long)];
// ... some code ...
fread(&aux,sizeof(unsigned long),1,fp);
Understand that char* aux[sizeof(unsigned long)]; means that you are declaring a double pointer, but fread() prototype states that the destination is a single pointer:
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
so what you should be doing instead is:
char aux[sizeof(unsigned long)];
// ... some code ...
fread(aux,sizeof(unsigned long),1,fp);
Don't complicate things that are not complicated!
You also do this mistake in other parts of your code, you need to re-check everything, ok? Again:
char *buffer2[28568];
fread(&buffer2,1,28568,fp);
should be:
char buffer2[28568];
fread(buffer2, 1, 28568, fp);
// or: fread(buffer2, 1, sizeof(buffer2), fp);
There are some interesting tutorials on pointers and arrays, I suggest you read some.