11 March 2014

Adding format specifiers to printf

It is possible to add specifiers for the printf function family. To do this, the register_printf_specifier can be used.
Two functions must be created for this.
int print_data_struture(FILE *stream, const struct printf_info *info, const void *const *args)
{
 char buffer[256];
 int len = 0;
 data_structure_t *data = 0;

 data = *((data_structure_t **)(args[0]));

 print_data_structure_to_string(buffer, data);

 len = fprintf(stream, "%*s", (info->left?-info->width:info->width), buffer);

 return len;
}

int print_data_structure_arginfo(FILE *stream, const struct printf_info *info, const void *const *args)
{
 if (n>0) {
  argtypes[0] = PA_POINTER;
  return 1;
 }
 return 0;
}

Afterwards, at the start of the program, the register_format_specifier must be called with the two functions and the specifier as parameters.
int main()
{
 register_print_specifier('W', print_data_structure, print_data_structure_arginfo);

 ...

 data_structure_t data;
 /* initialize data */

 ...

 printf("%W\n", &data); 

This should print the data variable as specified in the print_data_structure_to_string function. However, while the program will compile, there are two major issues with it.
Firstly, the register_format_specifier function is a GNU extension, it is not part of the ISO C standard.
Secondly, while the program will compile and execute correctly, the compiler (gcc) will give warnings when compiling with -Wformat (or -Wall), and these warnings cannot be avoided, since it is not possible to add specifiers to the ones supported by the gcc static check.

07 March 2014

Wireshark over SSH ... over SSH

Running Wireshark on a remote machine using SSH is not a very complex task, and there are many solutions for this on the web. However, the task becomes slightly more complex when you have to access a remote machine through another remote machine (e.g. you SSH to machine A and from there SSH to machine B).
This is the solution I found, using FIFO pipes.
On the remote machine where you have to listen, you create a FIFO pipe. You do the same thing on the intermediary machine.
mkfifo /tmp/wirefifo
After that, you read the pipe from the intermediary machine on the local host and pipe it to wireshark.
ssh user@hostA "cat /tmp/wirefifo"  | wireshark -k -i -
On the intermediary machine, you pipe the output of the machine you are listening for packets on to the local pipe.
ssh user@hostB "cat /tmp/wirefifo" > /tmp/wirefifo
The last step is to start tcpdump on the remote host and pipe the result to the FIFO pipe.
tcpdump -s 0 -U -n -w - -i any not port 22 > /tmp/wirefifo
Wireshark should now be showing the packets captured by tcpdump.