socket ethernet brut linux se lie à un protocole spécifique

J’écris du code pour envoyer des trames Ethernet brutes entre deux boîtiers Linux. Pour tester cela, je veux juste obtenir un simple client-envoi et serveur-réception.

J’ai le client correctement faire des paquets (je peux les voir en utilisant un renifleur de paquets).

Du côté du serveur, j’initialise le socket comme suit:

fd = socket(PF_PACKET, SOCK_RAW, htons(MY_ETH_PROTOCOL)); 

MY_ETH_PROTOCOL est une constante de 2 octets que j’utilise comme un ethertype, donc je n’entends pas de trafic réseau étranger.

quand je lie cette socket à mon interface, je dois lui transmettre à nouveau un protocole dans la structure socket_address.sll_protocol = htons(MY_ETH_PROTOCOL); : socket_address.sll_protocol = htons(MY_ETH_PROTOCOL);
Si je comstack et exécute le code comme celui-ci, cela échoue. Mon serveur ne voit pas le paquet. Cependant si je change le code comme ça:
socket_address.sll_protocol = htons(ETH_P_ALL);
Le serveur peut alors voir le paquet envoyé par le client (ainsi que de nombreux autres paquets). Je dois donc vérifier le paquet pour voir s’il correspond à MY_ETH_PROTOCOL .

Mais je ne veux pas que mon serveur entende du trafic qui n’est pas envoyé sur le protocole spécifié, ce n’est donc pas une solution. Comment puis-je faire cela?

    J’ai résolu le problème.

    Selon http://linuxreviews.org/dictionary/Ethernet/ faisant référence au champ de 2 octets suivant les adresses MAC:

    “les valeurs de ce champ entre 64 et 1522 indiquaient l’utilisation du nouveau format Ethernet 802.3 avec un champ de longueur, tandis que les valeurs de 1536 décimales (0600 hexadécimales) et supérieures indiquaient l’utilisation du format de trame DIX ou Ethernet d’origine avec un sous-système EtherType -identifiant de protocole. ”

    donc je dois m’assurer que mon ethertype est> = 0x0600.

    Selon http://standards.ieee.org/regauth/ethertype/eth.txt, l’ utilisation de 0x88b5 et 0x88b6 est “disponible pour un usage public pour le développement de protocoles prototypes et spécifiques à un fournisseur”. C’est donc ce que je vais utiliser comme un ethertype. Je ne devrais pas avoir besoin de filtrage supplémentaire car le kernel devrait s’assurer de ne prendre que les trames Ethernet avec l’adresse MAC de destination correcte et en utilisant ce protocole.

    J’ai déjà contourné ce problème en utilisant un filtre de paquets.

    Hand Waving (pseudocode non testé)

     struct bpf_insn my_filter[] = { ... } s = socket(PF_PACKET, SOCK_DGRAM, htons(protocol)); struct sock_fprog pf; pf.filter = my_filter; pf.len = my_filter_len; setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, &pf, sizeof(pf)); sll.sll_family = PF_PACKET; sll.sll_protocol = htons(protocol); sll.sll_ifindex = if_nametoindex("eth0"); bind(s, &sll, sizeof(sll)); 

    L’erreur de vérification et de récupération du filtre de paquets est laissée à l’exercice pour le lecteur …

    Selon votre application, libpcap est une alternative plus facile à utiliser.