How to get socket listening port from request_sock? [closed] - tcp

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed last month.
Improve this question
I am trying to capture the syn queue len and accept queue len by setting a kprobe on tcp_v4_syn_recv_sock, the logic would get the third param of it (request_sock) and get ir_num of the sock.
I have searched for it, and the ir_num seems to be the "local port". In my opinion, the "local port" is the listening port. However, the ir_num is very different from the listening port.
The ebpf code:
static __always_inline int request_sock_to_ring(struct filler_data *data, struct request_sock *sk)
{
u16 sport = 0;
u16 dport = 0;
u32 saddr = 0;
u32 daddr = 0;
u16 family = 0;
const struct inet_request_sock *ireq = inet_rsk(sk);
bpf_probe_read(&sport, sizeof(sport), (void *)&ireq->ir_rmt_port);
bpf_probe_read(&dport, sizeof(dport), (void *)&ireq->ir_num);
bpf_probe_read(&saddr, sizeof(saddr), (void *)&ireq->ir_rmt_addr);
bpf_probe_read(&daddr, sizeof(daddr), (void *)&ireq->ir_loc_addr);
bpf_probe_read(&family, sizeof(family), (void *)&sk->__req_common.skc_family);
sport = ntohs(sport);
int size = 1 + 4 + 4 + 2 + 2;
data->buf[data->state->tail_ctx.curoff & SCRATCH_SIZE_HALF] = socket_family_to_scap(family);
memcpy(&data->buf[(data->state->tail_ctx.curoff + 1) & SCRATCH_SIZE_HALF], &saddr, 4);
memcpy(&data->buf[(data->state->tail_ctx.curoff + 5) & SCRATCH_SIZE_HALF], &sport, 2);
memcpy(&data->buf[(data->state->tail_ctx.curoff + 7) & SCRATCH_SIZE_HALF], &daddr, 4);
memcpy(&data->buf[(data->state->tail_ctx.curoff + 11) & SCRATCH_SIZE_HALF], &dport, 2);
data->curarg_already_on_frame = true;
return bpf_val_to_ring_len(data, 0, size);
}
The log:
wrk-4122915 [003] dNs11 4843677.931047: bpf_trace_printk: saddr 16777343 daddr 16777343
wrk-4122915 [003] dNs11 4843677.931055: bpf_trace_printk: saddr 16777343 sport 33112 dport 16415
You can see the sport is 16415, but the real port is actually 8000. Do I get it wrong?

TL;DR. You're missing a call to ntohs for the destination port.
It's a common mistake so the first thing I checked is:
You can see the sport is 16415, but the real port is actually 8000. Do I get it wrong?
16415 is 0x401F; 8000 is 0x1F40. They just differ in byte ordering.

Related

Arduino IDE - global variables storage in RAM or flash memory

Conventional wisdom has it that global and static data is stored in the bottom of RAM along with other stuff. Somewhere above that is the heap, then free memory and at the top of RAM, is the stack. See the code below before reading on.
When I compile this with the Arduino IDE (1.8.10) on a MEGA2560 I get the following statistics:
Sketch uses 2750 bytes (1%) of program storage space. Maximum is 253952 bytes.
Global variables use 198 bytes (2%) of dynamic memory, leaving 7994 bytes for local variables. Maximum is 8192 bytes.
If I change ARRAY_SIZE from 1 to 7001, I get exactly the same numbers. I expected that dynamic memory should increase by 7000. When I do the same comparison with AtmelStudio V7, dynamic memory does indeed increase by 7000.
One more piece of information along these lines. If I do a malloc of 7000 which is pretty close to free memory, one would expect that the malloc should be successful when ARRAY_SIZE equals one and would fail when the ARRAY_SIZE equals 7001. I was dismayed to find that the malloc was successful with both the small and the large array sizes. With AtmelStudio this does not happen.
I suspect respective compiler/linker options somewhere could explain the difference (AtmelStudio - project properties and Arduino IDE - platform.txt perhaps?).
I also suspect that the Arduino IDE dynamically allocates global variables in FlashMemory.
I am not a newbie, but I am not a guru - comments anyone?
Thanks
Michèle
#define ARRAY_SIZE 7001
uint8_t globalArray[ARRAY_SIZE]{1};
void setup() {
Serial.begin(115200);
for (int i = 0; i < ARRAY_SIZE; i++) globalArray[i] = 1;
Serial.print(F("Just initialized globalArray, size = "));Serial.println(ARRAY_SIZE);
uint8_t* testPointer = (uint8_t*) malloc(7000);
Serial.print(F("Allocation of 7000 bytes "));
if ( testPointer != (uint8_t*) 0) {
Serial.print(F("SUCCESSFUL"));
} else {
Serial.print(F("NOT SUCCESSFUL"));
}
} // setup
void loop() {} // loop
I ran some more tests to figure out why AtmelStudio and the Arduino IDE are supplying vastly different RAM usage values after declaring an array. The response from juraj (thank you) was that the compiler optimized unused code away. This answer was true however I had included an array initialization loop to make sure that the compiler would include the array in the code.
It turns out that AtmelStudio and the Arduino IDE have different criteria as to code what it means "code being used". The outcome is that globalArray, in the initialization line,
for (int i = 0; i < ARRAY_SIZE; i++) globalArray[i] = 1;
is considered by AtmelStudio as being used and by the Arduino IDE as not being used.
The Arduino IDE requires that globalArray appear on the left of an assignment statement to consider it as being used thus the need for the "a+=globalArray[i];" line. The exact same code below reports:
a+=globalArray[i]; not used
Atmel Studio: Data Memory Usage as being 7211 bytes
Arduino IDE: Global variables use 198 bytes
a+=globalArray[i]; used
Atmel Studio: Data Memory Usage as being 7211 bytes
Arduino IDE: Global variables use 7199 bytes
Q.E.D. Interesting how the two IDEs do not quite mean the same thing with "being used".
Thanks - My first time on this forum got my question answered rather quickly.
Michèle
#define ARRAY_SIZE 7001
uint8_t globalArray[ARRAY_SIZE];
void setup() {
Serial.begin(115200);
for (int i = 0; i < ARRAY_SIZE; i++) globalArray[i] = 1;
Serial.print(F("Just initialized globalArray, size = "));
Serial.println(ARRAY_SIZE);
// uint16_t a {0};
// for (int i = 0; i < ARRAY_SIZE; i++) a+=globalArray[i];
// Serial.print(F("Value of a = ")); Serial.println(a);
uint8_t* testPointer = (uint8_t*) malloc(7000);
Serial.print(F("Allocation of 7000 bytes "));
if ( testPointer != (uint8_t*) 0) Serial.print(F("SUCCESSFUL"));
else Serial.print(F("NOT SUCCESSFUL"));
} // setup

How do I program an LCD to only use custom fonts? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I am working on a project where I need to use custom font only. I already defined all the Latin alphabets as byte arrays, so that I can simply copy the array value to the variable that's to be written. Below is a snippet of my code.
void menuInit() {
byte customChar1[8];
byte customChar2[8];
byte customChar3[8];
byte customChar4[8];
byte customChar5[8];
byte customChar6[8];
byte customChar7[8];
byte customChar8[8];
for (int i = 0; i <= 7; i++) {
customChar1[i] = H[i];
customChar2[i] = E[i];
customChar3[i] = A[i];
customChar4[i] = T[i];
}
lcd.createChar(0, customChar1);
lcd.createChar(1, customChar2);
lcd.createChar(2, customChar3);
lcd.createChar(3, customChar4);
lcd.setCursor(0, 0);
lcd.write(byte(0));
lcd.write(byte(1));
lcd.write(byte(2));
lcd.write(byte(3));
for (int i = 0; i <= 7; i++) {
customChar1[i] = C[i];
customChar2[i] = O[i];
customChar3[i] = O[i];
customChar4[i] = L[i];
}
lcd.createChar(0, customChar1);
lcd.createChar(1, customChar2);
lcd.createChar(2, customChar3);
lcd.createChar(3, customChar4);
lcd.setCursor(0, 1);
lcd.write(byte(0));
lcd.write(byte(1));
lcd.write(byte(2));
lcd.write(byte(3));
Arduino LCD documentation says that I need to write byte(int) in lcd.write() in order to print the created custom character. However, if I do that, I get two rows of "COOL" displayed on my LCD. It is probably because both the first row and second row are making reference to the same address. Is there any way I can copy the byte values to somewhere else and let it stay as it is?
Most character-mode LCDs come with a standard font in ROM and the ability to make a few custom characters (typically 8). Refer to your datasheet, but what you want is not possible in any LCD I've seen in the past ten years.
Graphical LCDs are different, as you "draw" on them whatever you want.

In Arduino, how do you write to port when port is a variable?

Examples of writing to a port seem to always use the port number as a constant, eg,
OCR2A = 180;
How do you write to the port when the port is unknown until run time. For example,
int port = (buttonPressed) ? 0x3b : 0x3c;
portWrite( port, 180 );
What I cannot find is the funtion portWrite(). Does something like that exist?
Robert's answer has some imprecise assertions and an incomplete answer.
Writing directly to port registers you can ruin other settings of the port and sometimes cause permanent damage to controller.
Can ruin other settings: true, you have to know what you are doing (for instance what pins are on the port you are manipulating, and know what are the functions you want to keep.
Can cause permanent damage: not really, or better not because of the port manipulation. If you wire a short circuit to ground and then set it as an output to 1, you can damage it whether you are using the port register or the digitalwrite. You have to be careful in both ways.
Now, returning to your problem, the enumeration is one way, but since the PORTB, PORTC, PORTD are just short name for values, you can set a variable and then use it to indirectly access it.
The type for this kind of variable is a volatile pointer to a byte (volatile means that write and read operations cannot be optimized by the compiler, since the value can change even between two operations):
volatile uint8_t *variablePortRegister;
You just have to load it with the address (so with the & symbol) of the register you want to change:
variablePortRegister = &PORTC;
then use the pointer to change the value
PORTC = 0x12;
becomes
(*variablePortRegister) = 0x12;
This is a short example. For it to work, connect a LED with resistor on arduino pin 5 (bit 5 of PORTD). The LED on the board (labeled L) is connected to pin 13 (bit 5 of PORTB).
The sketch will make one of the two leds blink for five times, then switch to the other. Only port manipulation instructions are used, and you can find that the way to read the port is the same as the one to write it.
volatile uint8_t *myportreg;
unsigned long lastTime;
uint8_t counter;
void setup() {
DDRB |= 0x20;
DDRD |= 0x20;
PORTB = 0;
PORTD = 0;
counter = 99; // trigger the register change immediately
}
void loop() {
if (counter >= 10)
{
counter = 0;
if (myportreg == &PORTD)
myportreg = &PORTB;
else
myportreg = &PORTD;
}
if ((millis() - lastTime) > 500)
{
lastTime = millis();
// change bit 5 of register
*myportreg = 0x20 ^ (*myportreg);
counter++;
}
}
EDIT: as Robert pointed out, it's much better to "use" just the pins you need (in this case, bit 5 of port B and D) rather than setting the whole port; this way you minimize the risk of screwing up something else. This edit is already included in the above code, so the code is correct
The port is a bit in one particular register. If you know the register and the position of the port in that particular register you can try this:
register = (1<<port) || register
to set the port to 1 and
register = (1<<port)^-1 && register
to set the port to 0.
Of course, you will need a switch somewhere to determine the register and the bit of the port in the register given the port name.

Should we frame whole packet ( headers , check sum, etc ) to use netmap?

I red about netmap which allows user programmers to access packets in the user space, that means user applications can read / send network packets very quickly using this netamp.
netmap :
http://info.iet.unipi.it/~luigi/netmap/
Can any one who are very familiar with netamp, tell me should we create entire packet that we want to send out, or we using the stack features to send it out.
Edit : here is example on how to use this api
https://www.freebsd.org/cgi/man.cgi?query=netmap&sektion=4
#include <net/netmap_user.h>
void sender(void)
{
struct netmap_if *nifp;
struct netmap_ring *ring;
struct nmreq nmr;
struct pollfd fds;
fd = open("/dev/netmap", O_RDWR);
bzero(&nmr, sizeof(nmr));
strcpy(nmr.nr_name, "ix0");
nmr.nm_version = NETMAP_API;
ioctl(fd, NIOCREGIF, &nmr);
p = mmap(0, nmr.nr_memsize, fd);
nifp = NETMAP_IF(p, nmr.nr_offset);
ring = NETMAP_TXRING(nifp, 0);
fds.fd = fd;
fds.events = POLLOUT;
for (;;) {
poll(&fds, 1, -1);
while (!nm_ring_empty(ring)) {
i = ring->cur;
buf = NETMAP_BUF(ring, ring->slot[i].buf_index);
// here they are saying to construct the packet
... prepare packet in buf ...
ring->slot[i].len = ... packet length ...
ring->head = ring->cur = nm_ring_next(ring, i);
}
}
}
You need to create entire packed, including ethernet, ip and tcp headers. Netmap completely bypasses kernel network stack, so you need to do all work yourself.

Sending char buffer through TCP socket incomplete

I'm just learning how to handle sockets and TCP connections in C. I've got an application (a long one) which basically sends and receives char arrays with the system call write from server to client and vice versa (two separate C applications of course). As long as I use it with a local connection, on the same PC, running the server on a terminal and the client on an another, everything just works fine and the data arrives at the destination. But if I try it with the server on one computer and the client on another but on the same internet line, passing to the client an address like 192.168.1.X (took from the machine on which the server is running), after the connection is established, I've got an error that tells me that the number of expected bytes (which I pass before sending the real char[]) isn't arrived. Same thing if I try the server on my PC, and the client on another one with a different line on a different provider.
There's something I'm missing, are there any limitations in sending a bunch of bytes in sequence?
The code where the error pops up.
SERVER SIDE:
r=htonl(lghstr);
w=write(myFd,&r,sizeof(int));//writes the number of incoming bytes
if(w<0) perror("writeServer4"),exit(-1);
w=write(myFd,tmp->string,lghstr);
if(w<0) perror("writeServer5"),exit(-1);
if(w!=lghstr) perror("ERROR");
CLIENT SIDE
rC=read(fdc,&cod,sizeof(int));//read incoming number of bytes
lghstr=ntohl(cod);
if(rC<0) perror("readClient3"),exit(-1);
rC=read(fdc,dest,lghstr);
if(rC<0) perror("readClient4"),exit(-1);
if(rC!=lghstr) perror("error : "), printf("didn't read the right number of bytes"),exit(-1);
Now this is basically repeated a lot of times, let's even say 300 times, and it's with big numbers that the program doesn't work.
This is the problem:
rC=read(fdc,dest,lghstr);
...
if(rC!=lghstr) perror("error : ")
The #1 fallacy with socket programming is expecting that recv() and read() will return exactly the same number of bytes corresponding to the write/send call made by the other side.
In reality, partial data is extremely likely and expected. The simple workaround is to loop on read/recv until you get the exact number of bytes expected:
size_t count = 0;
while (count < lghstr)
{
ssize_t readresult = read(fdc, dest+count, lghstr-count);
if (readresult == -1)
{
// socket error - handle appropriately (typically, just close the connection)
}
else if (readresult == 0)
{
// The other side closed the connection - handle appropriately (close the connection)
}
else
{
count += readresult;
}
}
The other alternative to looping is to the use the MSG_WAITALL flag with the socket. This means, using recv() instead of read(). You'll still need to handle the error cases.
rc = recv(fdc, dest, lghstr, MSG_WAITALL);
if (rc == -1)
{
// socket error
}
else if (rc == 0)
{
// socket closed by remote
}
else if (rc < lghstr)
{
// the other side likely closed the connection and this is residual data (next recv will return 0)
}
You do ntohl() on one side and not the other. That might be interpreting the bytes with the wrong value.
You should printf() the bytes on both sides and see what the int is being evaluated to.
Edit: I'm convinced this is a programming bug for the record.
If I had to guess, I'd say that you are not synchronous with the other side for some reason. You say this runs 'about 300 times'.
Try adding a magic integer to the protocol.
Heres an example of a client that sends in this order.
A magic integer which is always constant.
A lengh of bytes about to be sent.
The bytes to be sent.
This uses scatter gather mechanics (its nicer for serialization) but other than that it effectively is doing the same thing yours is doing, as a client, just adding a magic value.
When the receiver receives the data, it can validate that the data is coming in the right order, by checking what the magic number was that came in. If the magic is wrong it means the client or server has lost themselves positionally in the stream.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <err.h>
#include <time.h>
#define MAGIC 0xDEADBEEFLU
#define GARBAGE_MAX 65536
const int iterations = 3000;
char * create_garbage_buf(
void)
{
int rc = -1;
int fd = -1;
char *buf = NULL;
buf = malloc(GARBAGE_MAX);
if (!buf)
err(1, "Cannot allocate buf");
fd = open("/dev/urandom", O_RDONLY);
if (fd < 0)
err(1, "Cannot open urandom");
rc = read(fd, buf, GARBAGE_MAX);
if (rc < 0)
err(1, "Cannot read from urandom");
else if (rc != GARBAGE_MAX)
errx(1, "Expected %d bytes, but got %d reading from urandom",
GARBAGE_MAX, rc);
close(fd);
return buf;
}
int main() {
int fd, offset, i, rc;
uint32_t magic = MAGIC;
uint32_t blen = 0;
char *buf = NULL;
struct iovec vecs[3];
/* Seed poor random number generator */
srand(time(NULL));
/* Use a file for demonstration, but a socket will do just fine */
fd = open("/dev/null", O_WRONLY);
/* Create some garbage to send */
buf = create_garbage_buf();
if (fd < 0)
err(1, "Cannot open file");
/* The first vector, is always the magic */
vecs[0].iov_len = sizeof(uint32_t);
vecs[0].iov_base = &magic;
for (i=0; i < iterations; i++) {
/* The second vector represents lengh of what we send
* in this demonstration it is a number between 0 and
* GARBAGE_MAX/2.
*/
blen = rand() % (GARBAGE_MAX / 2);
vecs[1].iov_len = sizeof(uint32_t);
vecs[1].iov_base = &blen;
/* The last record is the data to send. Its another random
* number between 0 and GARBAGE_MAX which represents the offset
* in our garbage data to send */
offset = rand() % (GARBAGE_MAX / 2);
vecs[2].iov_len = blen;
vecs[2].iov_base = &buf[offset];
rc = writev(fd, vecs, 3);
if (rc < 0)
err(1, "Could not write data");
if (rc != (sizeof(uint32_t)*2 + blen))
errx(1, "Did not write proper number of bytes to handle");
printf("Wrote %u bytes from offset %u in garbage\n", blen, offset);
}
free(buf);
printf("Done!\n");
return 0;
}
Closely read the documentation for read()/write() and learn that those two functions do not necessarily read()/write() as much bytes as they were told to, but few. So looping around such calls counting until all data expected had been read/written is a good idea, not to say an essential necessity.
For examples how this could be done for writing you might like to have look at this answer: https://stackoverflow.com/a/24260280/694576 and for reading on this answer: https://stackoverflow.com/a/20149925/694576

Resources