Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Bibliotheque C pour changer l'en-tête IP (champs DSCP ou TOS)

4 réponses
Avatar
David
Bonjour,

j'aimerais savoir si quelqu'un connait une bibliothèque en C (linux)
permettant de changer le champs TOS (Type Of Service) ou le champs DSCP
(Diffserv Code Point) dans le but, vous l'aurez certainement compris, de
pouvoir envoyer un flux qui sera traité prioritairement au niveau des
routeurs traversés.

Je sais que cela peut se configurer au niveau de iptables (sous linux)
et au niveau des routeurs, mais je souhaiterais que mon application
émette directement un flux (voir dans l'absolu, certains paquets d'un
flux) avec la bonne en-tête IP.

Merci

4 réponses

Avatar
Marc Lasson
David wrote:
Bonjour,
Bonsoir,

vous l'aurez certainement compris
Ah non, moi j'ai compris que dalle :'(.


Je te conseille de reposter ta question sur fr.comp.os.unix tu aurai
plus de chances de trouver des gens qui captent.

--
Marc.

Computers in the future may weigh no more than 1.5 tons.
Popular Mechanics, 1949.

Avatar
Jean-Michel Bechet
j'aimerais savoir si quelqu'un connait une bibliothèque en C (linux)
permettant de changer le champs TOS (Type Of Service) ou le champs DSCP
(Diffserv Code Point) dans le but, vous l'aurez certainement compris, de
pouvoir envoyer un flux qui sera traité prioritairement au niveau des
routeurs traversés.

Je sais que cela peut se configurer au niveau de iptables (sous linux)
et au niveau des routeurs, mais je souhaiterais que mon application
émette directement un flux (voir dans l'absolu, certains paquets d'un
flux) avec la bonne en-tête IP.



pas besoin de biblithèque particulière; setsockopt avec le paramètre HDRINCL
te donne accès au header IP complet quand tu fais un read ou un write sur ta
socket. voir man setsockopt pour plus d'infos.

Avatar
Emmanuel Delahaye
In 'fr.comp.lang.c', "Jean-Michel Bechet" wrote:

pas besoin de biblithèque particulière; setsockopt avec le paramètre
HDRINCL te donne accès au header IP complet quand tu fais un read ou un
write sur ta socket. voir man setsockopt pour plus d'infos.


A part que ça n'a rien de standard... De quel système parles-tu? Avec quelle
implémentation?

--
-ed- [remove YOURBRA before answering me]
The C-language FAQ: http://www.eskimo.com/~scs/C-faq/top.html
C-reference: http://www.dinkumware.com/manuals/reader.aspx?lib=cpp
FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/

Avatar
Olivier Aumage
David writes:

j'aimerais savoir si quelqu'un connait une bibliothèque en C (linux)
permettant de changer le champs TOS (Type Of Service) ou le champs
DSCP (Diffserv Code Point) dans le but, vous l'aurez certainement
compris, de pouvoir envoyer un flux qui sera traité prioritairement au
niveau des routeurs traversés.

Je sais que cela peut se configurer au niveau de iptables (sous linux)
et au niveau des routeurs, mais je souhaiterais que mon application
émette directement un flux (voir dans l'absolu, certains paquets d'un
flux) avec la bonne en-tête IP.


Bonjour David,

(Suite sur fr.comp.os.unix ...)

Puisqu'il s'agit de linux, tu peux utiliser le périphérique (device)
/dev/tun qui permet d'allouer des interfaces réseau "virtuelles" dans
lesquelles tu peux injecter des paquets IP et également lire les
paquets qui sont routés vers ces interfaces.

Références:
- linux/Documentation/networking/tuntap.txt dans les sources du noyau
Linux.
- http://vtun.sourceforge.net/tun/ développement du pilote, sur le web


Le fichier ci-dessous est un exemple d'utilisation largement inspiré
des exemples du pilote. Il affiche une version "décodée" des paquets
IP qui sont routés vers l'interface virtuelle.

Note: il faut les droits d'accès 'rw' sur /dev/net/tun

Utilisation:
- tu lances le programme dans un terminal, il affiche le nom de
l'interface virtuelle qu'il a alloué:

$ ./read_tun
dev = tun0

- dans un second terminal, tu actives l'interface et tu fais par
exemple passer une route par celle-ci (ici on crée une route vers une
machine 192.168.0.2 qui n'existe pas):

$ ifconfig tun0 192.168.0.1
$ route add -host 192.168.0.2 gw 192.168.0.1 tun0

- tu testes le tout en faisant un ping sur 192.168.0.2, le programme
d'exemple doit afficher les paquets IP "décodés".

Tu peux modifier le programme pour faire tes manipulations sur les
paquets IP puis les réémettre. Eventuellement, tu peux utiliser deux
interfaces (une pour lire les paquets et une pour les renvoyer) si
c'est plus facile au niveau du routage.

%---- exemple.c ----------
#include <stdlib.h>
#include <stdio.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <linux/if_tun.h>
#include <fcntl.h>
#include <unistd.h>
#include <obstack.h>
#include <string.h>

#define obstack_chunk_alloc malloc
#define obstack_chunk_free free

struct s_ip_fixed {
unsigned long int version;
unsigned long int internet_header_length;
unsigned long int type_of_service;
unsigned long int total_length;
unsigned long int identification;
unsigned long int flag_reserved;
unsigned long int flag_DF;
unsigned long int flag_MF;
unsigned long int fragment_offset;
unsigned long int time_to_live;
unsigned long int protocol;
unsigned long int header_checksum;
unsigned long int source_address;
unsigned long int destination_address;
};

struct s_ip_option {
unsigned long int copied;
unsigned long int class;
unsigned long int number;
unsigned long int length;
unsigned char *data;
struct s_ip_option *next;
};

struct s_ip_payload {
unsigned long int length;
unsigned char *data;
};

struct s_ip {
struct s_ip_fixed *header;
struct s_ip_option *option;
struct s_ip_payload *payload;
};

struct s_packet {
unsigned int flags;
unsigned int protocol;
struct s_ip *ip;
};


struct s_buf {
unsigned char *data;
unsigned long int length;
unsigned long int data_length;
unsigned long int offset;
};

static struct obstack obs = {0};

int
tun_alloc(char *dev)
{
struct ifreq ifr;
int fd, err;

if( (fd = open("/dev/net/tun", O_RDWR)) < 0 ) {
perror("open");
return -1;
}

memset(&ifr, 0, sizeof(ifr));

/* Flags: IFF_TUN - TUN device (no Ethernet headers)
* IFF_TAP - TAP device
*
* IFF_NO_PI - Do not provide packet information
*/
ifr.ifr_flags = IFF_TUN;
if( *dev )
strncpy(ifr.ifr_name, dev, IFNAMSIZ);

if( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ){
perror("ioctl");
close(fd);
return err;
}
strcpy(dev, ifr.ifr_name);
return fd;
}

void *
omalloc(size_t len) {
return obstack_alloc (&obs, len);
}

void
ofree(void *ptr) {
obstack_free (&obs, ptr);
}

unsigned long int
remaining(struct s_buf *p_buf) {
return p_buf->data_length-p_buf->offset;
}

unsigned char
read_byte(struct s_buf *p_buf) {
if (remaining(p_buf)) {
return p_buf->data[p_buf->offset++];
}

return 0;
}

void
padding(struct s_buf *p_buf, int power_of_2) {
while (remaining(p_buf) && (p_buf->offset & (power_of_2-1))) {
p_buf->offset++;
}
}

void
read_nbyte(unsigned char *dst, struct s_buf *p_buf, unsigned long int length) {
if (p_buf->offset+length <= p_buf->data_length) {
memcpy(dst, p_buf->data+p_buf->offset, length);
p_buf->offset += length;
} else if (remaining(p_buf)) {
memcpy(dst, p_buf->data+p_buf->offset, remaining(p_buf));
p_buf->offset = p_buf->data_length;
}
}

unsigned int
read_word(struct s_buf *p_buf) {
unsigned int word = 0;

word |= ((unsigned int)read_byte(p_buf)) << 8;
word |= ((unsigned int)read_byte(p_buf)) << 0;

return word;
}

unsigned long int
read_qword(struct s_buf *p_buf) {
unsigned long int qword = 0;

qword |= ((unsigned int)read_byte(p_buf)) << 24;
qword |= ((unsigned int)read_byte(p_buf)) << 16;
qword |= ((unsigned int)read_byte(p_buf)) << 8;
qword |= ((unsigned int)read_byte(p_buf)) << 0;

return qword;
}

struct s_ip_fixed *
read_ip_fixed(struct s_buf *p_buf) {
struct s_ip_fixed *p_ip_fixed = NULL;
unsigned char b = 0;

p_ip_fixed = omalloc(sizeof(struct s_ip_fixed));

b = read_byte(p_buf);
p_ip_fixed->version = (b & 0xF0) >> 4;
p_ip_fixed->internet_header_length = b & 0x0F;

p_ip_fixed->type_of_service = read_byte(p_buf);
p_ip_fixed->total_length = read_word(p_buf);
p_ip_fixed->identification = read_word(p_buf);

b = read_byte(p_buf);
p_ip_fixed->flag_reserved = (b & 0x80) >> 7;
p_ip_fixed->flag_DF = (b & 0x40) >> 6;
p_ip_fixed->flag_MF = (b & 0x20) >> 5;
p_ip_fixed->fragment_offset (((unsigned long int)b & 0x1F) << 8) + read_byte(p_buf);

p_ip_fixed->time_to_live = read_byte(p_buf);
p_ip_fixed->protocol = read_byte(p_buf);
p_ip_fixed->header_checksum = read_word(p_buf);
p_ip_fixed->source_address = read_qword(p_buf);
p_ip_fixed->destination_address = read_qword(p_buf);

return p_ip_fixed;
}

struct s_ip_option *
read_ip_option(struct s_buf *p_buf, unsigned long int opt_len) {
unsigned long int opt_type = 0;
struct s_ip_option *p_ip_option = NULL;

if (!opt_len)
goto end;

p_ip_option = omalloc(sizeof(struct s_ip_option));

opt_type = read_byte(p_buf);

p_ip_option->copied = (opt_type & 0x80UL) >> 7;
p_ip_option->class = (opt_type & 0x60UL) >> 5;
p_ip_option->number = (opt_type & 0x1FUL) >> 0;

switch (p_ip_option->number) {

default:
return NULL;

case 0:
p_ip_option->length = 1;
p_ip_option->data = NULL;
p_ip_option->next = NULL;
opt_len--;
goto end;

case 1:
p_ip_option->length = 1;
opt_len--;
break;

case 2:
case 3:
case 4:
case 7:
case 8:
case 9:
p_ip_option->length = read_byte(p_buf);
p_ip_option->data = omalloc(p_ip_option->length);
read_nbyte(p_ip_option->data, p_buf, p_ip_option->length-2);

if (opt_len < p_ip_option->length) {
opt_len = 0;
} else {
opt_len -= p_ip_option->length;
}

break;
}

p_ip_option->next = read_ip_option(p_buf, opt_len);

end:
return p_ip_option;
}

struct s_ip_payload *
read_ip_payload(struct s_buf *p_buf, int length) {
struct s_ip_payload *p_ip_payload = NULL;

if (length) {
p_ip_payload = omalloc(sizeof(struct s_ip_payload));
p_ip_payload->length = length;
p_ip_payload->data = omalloc(p_ip_payload->length);
read_nbyte(p_ip_payload->data, p_buf, p_ip_payload->length);
}

return p_ip_payload;
}

struct s_ip *
read_ip(struct s_buf *p_buf) {
struct s_ip *p_ip = NULL;

p_ip = omalloc(sizeof(struct s_ip));

p_ip->header = read_ip_fixed(p_buf);
if (!p_ip->header) {
return NULL;
}

if (p_ip->header->internet_header_length > 5) {
unsigned long int opt_len =
(p_ip->header->internet_header_length-5) * 4;
p_ip->option = read_ip_option(p_buf, opt_len);
padding(p_buf, 4);
} else {
p_ip->option = NULL;
}

p_ip->payload = read_ip_payload(p_buf,
p_ip->header->total_length
- 4*p_ip->header->internet_header_length);

return p_ip;
}

struct s_packet *
read_packet(struct s_buf *p_buf) {
struct s_packet *p_packet = NULL;

p_packet = omalloc(sizeof(struct s_packet));

p_packet->flags = read_word(p_buf);
p_packet->protocol = read_word(p_buf);
p_packet->ip = read_ip(p_buf);

return p_packet;
}

void
newline(void) {
printf("n");
};

void
print_ip_addr(unsigned long int addr) {
unsigned int a = (addr >> 24) & 0xFF;
unsigned int b = (addr >> 16) & 0xFF;
unsigned int c = (addr >> 8) & 0xFF;
unsigned int d = (addr >> 0) & 0xFF;

printf("%d.%d.%d.%d", a, b, c, d);
}

void
print_bloc(unsigned char *data, unsigned long int length) {
unsigned long int i = 0;

for (i = 0; i < length; i++) {
unsigned char c = data[i];
unsigned char a = 0;
unsigned char b = 0;

if (!(i%16)) {
printf("n%04x:", (unsigned int)i);
}

a = (c >> 7) & 0xF;
b = c & 0xF;

if (!(i%4)) {
printf("t");
} else {
printf(" ");
}

printf("%1x%1x", a, b);
}
}


void
print_payload(struct s_ip_payload *p_ip_payload) {

if (!p_ip_payload || !p_ip_payload->length) {
printf("No payloadn");
return;
}

printf("Payload:");
print_bloc(p_ip_payload->data, p_ip_payload->length);
newline();
}

void
print_option(struct s_ip_option *p_ip_option) {
if (!p_ip_option)
return;

newline();
printf("Option:n");
printf("copied = %lxn", p_ip_option->copied);
printf("class = %lxn", p_ip_option->class );
printf("number = %lxn", p_ip_option->number);
printf("length = %lxn", p_ip_option->length);
if (p_ip_option->data) {
printf("option data:");
print_bloc(p_ip_option->data, p_ip_option->length - 2);
newline();
}

print_option(p_ip_option->next);
}

void
print_ip(struct s_ip *p_ip) {
printf("version = %lxn", p_ip->header->version );
printf("internet_header_length = %lxn", p_ip->header->internet_header_length );
printf("type_of_service = %lxn", p_ip->header->type_of_service );
printf("total_length = %lxn", p_ip->header->total_length );
printf("identification = %lxn", p_ip->header->identification );
printf("flag_reserved = %lxn", p_ip->header->flag_reserved );
printf("flag_DF = %lxn", p_ip->header->flag_DF );
printf("flag_MF = %lxn", p_ip->header->flag_MF );
printf("fragment_offset = %lxn", p_ip->header->fragment_offset );
printf("time_to_live = %lxn", p_ip->header->time_to_live );
printf("protocol = %lxn", p_ip->header->protocol );
printf("header_checksum = %lxn", p_ip->header->header_checksum );

printf("source_address = %lx ", p_ip->header->source_address );
print_ip_addr(p_ip->header->source_address);
newline();

printf("destination_address = %lx ", p_ip->header->destination_address );
print_ip_addr(p_ip->header->destination_address);
newline();
print_option(p_ip->option);
newline();
print_payload(p_ip->payload);
}

void
print_packet(struct s_packet *p_packet) {
printf ("Flags: %4xn", p_packet->flags);
printf ("Proto: %4xn", p_packet->protocol);
if (p_packet->ip) {
print_ip(p_packet->ip);
}
}


int
main(int argc, char **argv) {
char dev[64] = {0};
int fd = -1;

fd = tun_alloc(dev);
printf("dev = %sn", dev);

if (fd < 0)
return 1;

while (1) {
struct s_buf *p_buf = NULL;
struct s_packet *p_packet = NULL;
int s = 0;

obstack_init (&obs);

p_buf = omalloc(sizeof(struct s_buf));

p_buf->length = 65536;
p_buf->data_length = 0;
p_buf->offset = 0;
p_buf->data = omalloc(65536);

s = read(fd, p_buf->data, p_buf->length);

if (!s) {
break;
}

if (s < 0) {
close(fd);
return 1;
}

p_buf->data_length = s;

p_packet = read_packet(p_buf);
if (p_packet) {
printf ("Packet:n");
print_packet(p_packet);
} else {
printf("n<Error while reading packet>n");
ofree(NULL);
break;
}

ofree(NULL);

printf("n");
}

close(fd);

return 0;
}
%--------------------

--
Olivier