¿Cómo vincular un Socket Raw a un puerto específico?
network-programming raw-sockets (2)
Actualmente estoy trabajando en una tarea de programación. La tarea es implementar un cliente, un emulador de red y un servidor. El cliente pasa los paquetes a un emulador de red y el emulador de red pasa al servidor. Viceversa también se aplica. El requisito previo para la asignación es que solo puedo usar conectores crudos. Así que crearé mis propios encabezados de IP y UDP. He probado mis paquetes con wireshark. Todos son correctos y están en el formato correcto (los lee correctamente).
Otro requisito es que el emulador, el cliente y el servidor tengan puertos específicos a los que deben estar vinculados. Ahora, no entiendo cómo vincular un socket sin formato a un puerto específico. Todos mis sockets sin procesar reciben todo el tráfico en la dirección de host a la que están vinculados. Según las páginas de manual, y en cualquier otro sitio en Internet, incluida la "Programación de red Unix" de Richard Stevens, así es como se supone que funcionan. Mi profesor no ha respondido a ninguno de mis correos electrónicos y probablemente no pueda preguntarle hasta el martes. Veo dos opciones frente a mí. Primero puedo usar libpcap para filtrar desde un dispositivo específico y luego enviarlo a mi socket sin procesar. Sin embargo, siento que esto está fuera del alcance de nuestra tarea. O puedo filtrarlos después de recibirlos del socket. Esto aparentemente tiene una sobrecarga porque todos los paquetes se están copiando / moviendo a través del kernel. Al menos, eso es lo que entiendo (por favor, siéntete libre de corregirme si estoy equivocado).
Entonces mi pregunta es: ¿es una opción o algo que pueda establecer para esto? Donde el zócalo sin procesar se unirá a un puerto? ¿Me he perdido algo obvio?
Gracias por tu tiempo.
-
La página man para raw (7) dice:
Un socket sin formato puede vincularse a una dirección local específica utilizando la llamada bind (2). Si no está vinculado, se reciben todos los paquetes con el protocolo IP especificado. Además, un socket RAW puede vincularse a un dispositivo de red específico utilizando SO_BINDTODEVICE; ver el zócalo (7).
Editar: No puede vincular un socket sin formato a un puerto específico porque "puerto" es un concepto en TCP y UDP, no IP. Observe los diagramas de encabezado para esos tres protocolos y debería ser obvio: está trabajando en un nivel inferior, donde no se conoce el concepto de puerto.
Creo que se espera que filtren los paquetes en su software. Parece que el ejercicio consiste en aprender qué hacen los diferentes componentes de la pila de IP recreando una parte simplificada en el espacio de usuario. Normalmente en el kernel, el código IP procesa todos los paquetes, verifica los encabezados de IP, vuelve a armar fragmentos y verifica el campo de protocolo. Si el campo de protocolo es 17 (udp), lo pasa al código UDP (cada paquete UDP). Depende del código UDP para validar el encabezado UDP y determinar si las aplicaciones están interesadas en ellos en función del puerto de destino.
Me imagino que se espera que su proyecto imite más o menos este proceso. Obviamente, nada de esto será tan eficiente como hacerlo en el kernel, pero como la tarea es escribir (parte de) una pila de IP en el espacio de usuario, supongo que la eficiencia no es el objetivo del ejercicio.