Raw Sockets: Receptor imprimiendo valores basura

Estoy tratando de enviar una matriz de caracteres usando un transmisor y un programa receptor usando sockets sin formato. Puedo obtener la cantidad correcta de bytes enviados en el lado del receptor, pero los valores impresos son basura. ¿Podría alguien ayudarme aquí?

Transmisor:

int create_raw_socket(char *dev) 
{   
struct sockaddr_ll sll;
struct ifreq ifr;
int fd, ifi, rb;

bzero(&sll, sizeof(sll)); 
    bzero(&ifr, sizeof(ifr));

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

assert(fd != -1);

strncpy((char *)ifr.ifr_name, dev, IFNAMSIZ);
ifi = ioctl(fd, SIOCGIFINDEX, &ifr);
assert(ifi != -1);
sll.sll_protocol = htons(ETH_P_ALL);
sll.sll_family = AF_PACKET;
sll.sll_ifindex = ifr.ifr_ifindex;
rb = bind(fd, (struct sockaddr *)&sll,sizeof(sll));
assert(rb != -1);

return fd;  
 }


int SendPacket(char *dev ,unsigned char *send_packet, int packet_len) 
{
   int num_sent= 0;
   int sockaddress = create_raw_socket(dev);

   if((num_sent = write(sockaddress, &send_packet, packet_len)) != packet_len)
     { 

         close(sockaddress);
          return 0;
     } 
   else
     { 
        close(sockaddress);
         return 1; 
     }

  }


int main(int argc, char**argv)
{
   int x,fd,s; 

    char *send_packet="HELLO";

   int len = sizeof(send_packet);

   while(1)
   {

   if(!SendPacket((argv[1]), send_packet, len))
     perror("Error sending packet");
   else
     printf("Packet sent successfully with payload : %s\n" ,send_packet);
   }
    return 0; 
 }

Receptor

int main(int argc, char **argv)
{
 struct sockaddr addr;
 int sock_fd, fromlen,s;
 char buf[PACKET_LENGTH];
 char *dev = argv[1];


 while(1)
 {

   fromlen=sizeof(addr);
   sock_fd = create_raw_socket(dev);   /* Creating the raw socket */
   int x= recvfrom(sock_fd,&buf,sizeof(buf),0,&addr,&fromlen);
   printf("\n Number of bytes of data received is %d \n",x);

   printf("\nPayload  Received from client... is %s \n", buf);

   close(sock_fd);

 }
 return 0;
 }

preguntado el 22 de mayo de 12 a las 16:05

3 Respuestas

Cambiar

write(sockaddress, &send_packet, packet_len)

a

write(sockaddress, send_packet, packet_len)

send_packet ya es la dirección del búfer a enviar, si toma la dirección de esta dirección (más precisamente, la dirección de la variable que contiene la dirección), leerá la memoria incorrecta para el búfer

Similarmente para recvfrom:

recvfrom(sock_fd, buf, sizeof(buf), 0, &addr, &fromlen)

contestado el 22 de mayo de 12 a las 16:05

Eso es correcto para el write llamar, ya que send_packet es un puntero, pero no hace ninguna diferencia para la llamada a recvfrom, Desde buf es una matriz. Los tipos de matriz tienen la propiedad de que su dirección es numéricamente equivalente a la dirección de su primer elemento, por lo que para una matriz x, siempre es cierto que (void*)&x == (void*)&x[0]. - adam rosenfield

Tienes varios problemas:

  1. Esta línea

    if((num_sent = write(sockaddress, &send_packet, packet_len)) != packet_len)
    

    Debería decir solo send_packet en lugar de &send_packet. send_packet es un puntero que apunta al paquete de datos deseado, por lo que no es necesario tomar su dirección; no desea escribir la dirección literal de ese puntero en el paquete, eso simplemente no funcionará.

  2. Esto está mal:

    char *send_packet="HELLO";
    int len = sizeof(send_packet);
    

    sizeof(send_packet) siempre tendrá el tamaño de un puntero en su sistema, típicamente 4 u 8 bytes. Realmente quieres declarar send_packet como un tipo de matriz (por ejemplo char send_packet[] = ...), o usar strlen para calcular su longitud en tiempo de ejecución (por ejemplo, int len = strlen(send_packet) + 1;). En su caso, está enviando muy pocos datos (4 bytes) o demasiados datos (8 bytes), los cuales son problemáticos.

  3. Tus printf El código en el cliente asume que los datos que recibe están terminados en nulo, lo cual no es necesariamente. Debe anular manualmente los datos antes de imprimirlos (o usar cualquier otra función de cadena, para el caso), o decirle printf el límite de la cantidad de datos para imprimir. Sugeriría terminarlo en nulo así:

    char buf[PACKET_LENGTH + 1];  // +1 for null terminator
    int x = recvfrom(sock_fd,buf,PACKET_LENGTH,0,&addr,&fromlen);
    if(x >= 0)
        buf[x] = 0;
    
  4. Su código tiene mala const exactitud. SendPacket debería tomar un const char* en lugar de char* parámetro, y send_packet debe ser declarado como char[] o como const char*. La conversión de cadenas literales a char* está en desuso y debe evitarse en todo el código C nuevo.

contestado el 22 de mayo de 12 a las 16:05

Gracias por señalar todo el problema. Lo corregiré en mi código. Gracias de nuevo. - hektor

El uso de printf para imprimir el búfer imprimirá una cadena hasta que se alcance el final del carácter de cadena. Si ve la cadena original seguida de caracteres basura, esta puede ser la razón.

Probablemente debería introducir un 0 después del último byte devuelto por recvfrom, o imprimirá cualquier valor que haya en la memoria que recvfrom no sobrescribió. Incluso podría intentar acceder a la memoria fuera del búfer.

Intente agregar algo como:

int x= recvfrom(sock_fd,&buf,sizeof(buf) - 1,0,&addr,&fromlen);
buf[x - 1] = 0;

Nota: eso cambia el tamaño máximo de lo que se lee, es solo un ejemplo de cómo hacerlo.

contestado el 22 de mayo de 12 a las 16:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.