La Fibre
Datacenter et équipements réseaux => Routeurs =>
OpenWrt => Discussion démarrée par: basilix le 28 septembre 2024 à 08:34:57
-
Hello!
Je voudrais intégrer plusieurs options DHCPv4 dans le serveur odhcpd (https://github.com/openwrt/odhcpd) (codé en C). J'ouvre ce fil de discussion pour rester motivé et recevoir potentiellement un peu d'aide.
Il y a beaucoup de code à lire (plusieurs centaines de lignes). L'ensemble des sources odhcpd fait approximativement 10 000 lignes. Il faut également rajouter les sources
des bibliothèques : blob & Co. (blob.c, blobmsg.c), libuci... Cela me semble effectivement plus abordable de lire le code des bibliothèques au préalable. Mon problème est
que je ne suis pas sûr de bien comprendre le code. Il faut lire successivement plusieurs fonctions pour se faire une représentation car le code ne contient quasiment aucune
indication sous forme de commentaire et il n'y a pas de documentation (présentation très sommaire : c.f. libubox/blob.h (https://openwrt.org/docs/techref/libubox#libuboxblobh)).
Est-ce que les gens intéressés par odhcpd pourraient-ils répondre à quelques questions ?
-
Pourquoi la fonction blob_new (libubox: blob.c) réinitialise la longueur (encodée dans la valeur) du champ id_len (https://github.com/openwrt/libubox/blob/master/blob.c#L131) de l' « attribut » buf->head (struct blob_attr *ptr (https://lxr.openwrt.org/source/libubox/blob.h#L65)) ?
Il me semble que cela représente un emplacement mémoire alloué à deux options.
-
Quelle est l'utilité de la constante BLOB_COOKIE (blob.h (https://github.com/openwrt/libubox/blob/master/blob.h#L31)) ?
static inline struct blob_attr *
offset_to_attr(struct blob_buf *buf, int offset)
{
void *ptr = (char *)buf->buf + offset - BLOB_COOKIE;
return ptr;
}
static inline int
attr_to_offset(struct blob_buf *buf, struct blob_attr *attr)
{
return (char *)attr - (char *) buf->buf + BLOB_COOKIE;
}
bool
blob_buf_grow(struct blob_buf *buf, int required)
{
int offset_head = attr_to_offset(buf, buf->head);
if ((buf->buflen + required) > BLOB_ATTR_LEN_MASK)
return false;
if (!buf->grow || !buf->grow(buf, required))
return false;
buf->head = offset_to_attr(buf, offset_head);
return true;
}
static struct blob_attr *
blob_add(struct blob_buf *buf, struct blob_attr *pos, int id, int payload)
{
int offset = attr_to_offset(buf, pos);
int required = (offset - BLOB_COOKIE + sizeof(struct blob_attr) + payload) - buf->buflen;
struct blob_attr *attr;
if (required > 0) {
if (!blob_buf_grow(buf, required))
return NULL;
attr = offset_to_attr(buf, offset);
} else {
attr = pos;
}
blob_init(attr, id, payload + sizeof(struct blob_attr));
blob_fill_pad(attr);
return attr;
}
Elle semble intervenir dans un décalage relatif (offset) par rapport à l'adresse initiale de l'emplacement mémoire utilisé comme tampon (buf->buf).
Mon problème est le suivant : il me semble qu'on ajoute sa valeur à offset sauf qu'on finit par la soustraire, et donc, on annule son valeur. Du coup,
je ne saisis pas quel est l'effet recherché.
Code source : bibliothèque blob.c (https://github.com/openwrt/libubox/blob/master/blob.c#L43)
-
Bonjour basilix,
Je ne pense pas que ce soit sur le forum lafibre que tu trouveras réponses aux questions de code d'applications/firmwares spécifiques et de librairies dédiées à ces applications/firmwares :-\
-
@xp25 :
Je ne pense pas non plus. Je n'ai pas eu de réponse sur le forum OpenWrt. Néanmoins, il semble y avoir beaucoup de visites sur le forum lafibre. De plus, le langage C
est un langage assez courant. On pourrait penser que cela inciterait éventuellement des gens connaissant le C et utilisant OpenWrt à jeter un coup d’œil aux sources.
C'est aussi un moyen de rester motivé et exploiter pleinement l'accès au code (licence libre ou ouverte).
-
Je crois avoir percé la mystérieuse fonction blob_new. Dans l'ensemble, le code me semble difficile à interpréter.
Lorsque l'emplacement mémoire disponible est insuffisant pour stocker nos objets binaires alors on l'étend par bloc.
Il me semble que le pointeur buf->head ne désigne pas le dernier objet placé en mémoire tampon mais le premier
objet alloué lors d'une (ré-)allocation. C'est comme dans une représentation fragmentée de la mémoire tampon :
on obtiendrait plusieurs tampons juxtaposés dans le même emplacement mémoire. En conséquence, chaque
mémoire tampon définirait la taille de l'emplacement occupé par des attributs (blob_attr) dans le premier objet
blob_attr alloué lors d'une (ré-)allocation.
J'avais mal compris le code. buf->head contient l'adresse de l'emplacement mémoire alloué dynamiquement par
realloc (buf->buf). On y place un objet blob_attr pour créer la mémoire tampon. En fait, buf->head pointe
sur un objet blob_attr tel que défini par la structure blob_buf. Le code est particulièrement difficile à saisir
à cause de subtilités qui ne sont nullement expliquées, lesquelles contribuent à obscurcir le code. Je pense
notamment aux fonctions offset_to_attr, attr_to_offset et au symbole du préprocesseur (une constante)
BLOB_COOKIE.
-
Option d'authentification (90)
Le code d'authentification de message peut être généré par divers protocoles (et algorithmes).
Protocol Name Space Values
0 configuration token [RFC3118]
1 delayed authentication [RFC3118]
2 Delayed Authentication (Obsolete) [RFC8415]
3 Reconfigure Key [RFC8415]
4 Split-horizon DNS [RFC-ietf-add-split-horizon-authority-14]
Source : Dynamic Host Configuration Protocol (DHCP) Authentication Option Name Spaces (https://www.iana.org/assignments/auth-namespaces/auth-namespaces.xhtml)
Orange utilise le protocole « configuration token » avec l'algorithme du même nom. Dans ma capture réseau, la valeur du champ Replay Detection reste à 0.
The configuration token authentication mechanism is vulnerable to interception and provides only the most rudimentary protection
against inadvertently instantiated DHCP servers.
Il n'est pas précisé dans le RFC 3118 ce qu'apporte l'option d'authentification générée avec le protocole « configuration token », celle contenue dans un message client.
Conclusion :
Je pourrais sûrement tricoter une option 90 dans odhcpd sans y passer trois plombes pour faire fonctionner la téléphonie Orange fixe.
-
Je suis parvenu à pousser cette option d'authentification dans le code DHCPv4 de odhcpd [1]. Je n'ai pas réussi à implémenter le protocole « configuration token » (trop démoralisé).
De plus, je ne sais pas comment la pousser dans le code DHCPv6 de odhcpd. Le code dans cette partie est trop compact, j'ai eu de la chance de réussir à deviner pour la partie
dhcpv4. Je croyais au début que l'on transmettait les informations avec blobmsg alors que cela ne sert que de format pour extraire les données. L'encodage est défini dans les
RFC et peut se réaliser au moyen de structures en « mode binaire ».
[1] Code source non publié.