Hace mucho tiempo los usuarios de madwifi contábamos con un driver maravilloso que nos permitía hacer casi cualquier cosa con nuestra tarjeta WiFi. El driver pasó al mainstream de Linux y de repente, en una aciaga versión 2.6.18 (o por ahí) el driver dejó de inyectar. Muchos pensábamos que sería cuestión de tiempo que reparasen este bug... versión tras versión no hemos podido volver a inyectar y en los foros sobre el driver nadie parece haberse dado cuenta... y eso es porque el driver internamente nunca dejó de inyectar. Esta receta explica cómo hacer que el driver funcione como antaño, cuando todos éramos felices inyectando.
Bueno, como decíamos en la introducción, el driver nunca dejó de inyectar, sin embargo, las aplicaciones que hacen uso de esta feature no funcionan o dicen que el chipset no es capaz de inyectar. ¿Cómo es esto posible?. Para responder a esta pregunta quizás primero debamos saber qué características tiene el driver y el tráfico wifi.
El driver tiene dos partes bien diferenciadas: capa MAC80211 o interfaz con el sistema operativo y capa ATH_HAL o interfaz con el hardware. Ambas capas tienen colas de envío y recepción. Los frames o paquetes recibidos por ATH_HAL son procesados y pasados a las colas de la capa MAC80211 si es necesario. Los paquetes envíados a la capa MAC80211 son tratados y depositados en las colas de la capa ATH_HAL para ser envíados por el hardware.
La inyección es tratada por la capa MAC80211, sin embargo, ATH_HAL no marca ese tráfico como lo hacía antiguamente. Éste es el motivo por el que ahora parece que no inyectamos tráfico.
Bueno, cuando nuestro driver trabaja con tráfico normal, la cola de envío en la capa MAC80211 no realiza un marcaje especial de los frames, lo que implica que todos los paquetes envíados esperarán su correspondiente ACK. La capa MAC puede configurar su cola de envío de forma que marque los frames para que no esperen respuesta. Éste método es el que se debe usar cuando la cola de envío esté en modo inyección. Y ésto es lo que actualmente se ha eliminado del driver: cuando la cola de envío está en modo inyección, los paquetes en ATH_HAL son tratados como tráfico corriente, cuando en realidad deberían marcarse como NO_ACK.
Actualmente lo que sucede es que los paquetes inyectados esperan ACK, pero jamás lo recibirán puesto que son inyectados. Por este motivo son descartados por el propio ATH_HAL. Para que sean procesados y enviados por ATH_HAL sin importar si llegan o no los ACK hay que marcar el tráfico como NO_ACK.
Bueno, aquí depende del módulo que use nuestro chipset:
static int ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, struct ath5k_txq *txq) { ... flags = AR5K_TXDESC_INTREQ | AR5K_TXDESC_CLRDMASK; ... if (info->flags & IEEE80211_TX_CTL_NO_ACK) flags |= AR5K_TXDESC_NOACK; ... }
La función ath5k_txbuf_setup() configura la cola de envío (como su propio nombre indica) y, efectivamente, vemos que si la cola se configura como IEEE80211_TX_CTL_NO_ACK, añade AR5K_TXDESC_NOACK a los flags de envío. Sin embargo, no hace ningún cambio si la cola está en modo INJECTED.
static int setup_tx_flags(struct ath_softc *sc, struct sk_buff *skb, struct ath_txq *txq) { struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); int flags = 0; flags |= ATH9K_TXDESC_CLRDMASK; /* needed for crypto errors */ flags |= ATH9K_TXDESC_INTREQ; if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) flags |= ATH9K_TXDESC_NOACK; return flags; }
Efectivamente, la función aquí es setup_tx_flags(), que retorna los flags que usará la capa ATH_HAL en su cola de envío. Al igual que antes, no hace nada especial si la cola de la capa MAC80211 se configuró como INJECTED.
Ahora explicaremos como parchear el módulo en cuatro fáciles pasos, es un poco artesanal pero también más genérico (no voy a hacer parches para cada posible versión del driver :P).
Como ya dijeramos, los drivers madwifi pertenecen al mainstream de linux por lo que obtener los fuentes de forma separa puede no ser tan fácil como parece. En nuestro caso tenemos suerte y podemos descargar el paquete compat-wireless de Linux Wireless. Nos bajamos aquel cuya versión sea la más cercana a la de nuestro núcleo, en mi caso la 2.6.32:
$ wget http://www.orbit-lab.org/kernel/compat-wireless-2.6-stable/v2.6.32/compat-wireless-2.6.32.3.tar.bz2
$ unp compat-wireless-2.6.32.3.tar.bz2
$ cd compat-wireless-2.6.32.3
$ sudo aptitude install module-assistant
$ sudo m-a prepare
Con esto habremos instalado los programas y paquetes necesarios para compilar módulos para nuestro núcleo.
ATENCIÓN: estas modificaciones parecen ser motivos de cuelgues en núcleos con versiones 2.6.27 y similares.
Antes disponíamos de parches oficiales de madwifi pero ahora no hay (o no los encuentro) así que a manita... según el módulo que use nuestro chipset (con lsmod podemos ver cuál es):
if (info->flags & IEEE80211_TX_CTL_NO_ACK) flags |= AR5K_TXDESC_NOACK;
if (info->flags & IEEE80211_TX_CTL_NO_ACK || (info->flags & IEEE80211_TX_CTL_INJECTED && !(ieee80211_has_morefrags(((struct ieee80211_hdr *)skb->data)->frame_control)))) flags |= AR5K_TXDESC_NOACK;
if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) flags |= ATH9K_TXDESC_NOACK;
if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK || (tx_info->flags & IEEE80211_TX_CTL_INJECTED && !(ieee80211_has_morefrags(((struct ieee80211_hdr *)skb->data)->frame_control)))) flags |= ATH9K_TXDESC_NOACK;
Como véis, lo único que hacemos es añadir una condición más al if para marcar el tráfico como NO_ACK, y es que la cola esté configurada como INJECTED.
Si todo lo anterio lo hicimos correctamente, la compilación es lo más sencillo:
Bueno, el Makefile tiene el target install con lo que:
$ sudo make install
debería funcionar a la perfección, sin embargo, yo he hecho la instalación manual que consiste básicamente (esto es para ath9k, para el módulo ath5k se hará igual... solo cambia un fichero...):
¡Y listo! :D
Comentarios
Perfecto
Todo hecho al pie de la letra y módulos cargadas y funcionando... eso si, me queda probar la inyección
¡Por cierto! No estaría de más, aunque parezca obvio, que se necesitan tener los "headers" del kernel para poder compilar el módulo.
Saludos
Corregido
Gracias por el aporte!
------------------------------------------------------------
$ python -c "print 'VG9udG8gZWwgcXVlIGxvIGxlYSA6KQ==\n'.decode('base64')"
------------------------------------------------------------
Genial...
muy útil. Gracias
habrá que probarlo...
habrá que probarlo...
No soy portavoz de ningún colectivo, grupo o facción. Mi opinión es personal e intransferible.