2017-08-12 4 views
0

J'ai essayé d'écrire un petit programme traceroute propre en C pour Linux en utilisant des sockets raw, mais quand je compile, je reçois le message d'erreur "dereferencing pointeur vers type incomplet "struct ip.Erreur "déréférencer le pointeur vers le type incomplet" en essayant d'écrire à une structure

Ce sont les en-têtes Inclure:

#include <netinet/ip.h>   
#include <netinet/ip_icmp.h>   
#include <sys/socket.h>   
#include <stdlib.h>    
#include <stdio.h>    
#include <sys/types.h> 
#include <errno.h> 
#include <netdb.h> 
#include <arpa/inet.h> 
#include <ifaddrs.h> 

puis comment j'utiliser l'en-tête IP

struct ip *myIpHeader = (struct ip*)buffr; 

suivi d'un tas de choses ... alors:

myIpHeader->ip_v = 4;       
myIpHeader->ip_hl = 5;      
myIpHeader->ip_tos = 0;            
myIpHeader->ip_len = 20+8;     
myIpHeader->ip_off = 0;      
myIpHeader->ip_p = IPPROTO_ICMP;     
inet_pton(AF_INET, argv[1], &(myIpHeader->ip_dst)); 
inet_pton(AF_INET, ownip->h_name, &(myIpHeader->ip_src)); 
myIpHeader->ip_sum = 0;      
myIpHeader->ip_id = htonl(12345);      
myIpHeader->ip_ttl = ttl; 

Et puis je l'utilise pour l'envoi:

sendto(mysock, buffr, sizeof myIpHeader + sizeof myicmphead, 0, (struct sockaddr*)&cliAddr, sizeof cliAddr); 
+1

Afficher la définition et la déclaration complètes, vous avez probablement déclaré une structure sans nom. –

+1

Non, vous ne pouvez pas avoir de pointeur vers un type de structure anonyme sans que le type référencé soit terminé, car vous ne pouvez pas référencer un type de structure anonyme en dehors de la portée de sa définition. Parce que c'est, tu sais, anonyme. –

+1

Mais vous * pouvez * avoir un pointeur vers un type de structure nommé dont la définition n'est pas dans la portée. Vous pouvez contourner un tel pointeur, mais ne pas le déréférencer. –

Répondre

1

Transférer un commentaire dans une réponse.

Sur un Mac, l'en-tête <netinet/ip.h> contient une struct ip - mais ce n'est pas un en-tête normalisé par POSIX. C'est aussi là sous Linux (Ubuntu 16.04). Donc, il semble que lorsque vous faites le déréférencement, vous n'avez pas l'en-tête inclus, ou le contenu de l'en-tête est «invisible». Vous compilez avec -std=gnu11 ou -std=c11? Dans ce dernier cas, vous devez probablement activer les définitions POSIX (ou GNU). C'est plus facilement corrigé en utilisant -std=gnu11 à la place. Vous pouvez également utiliser -D_GNU_SOURCE ou -D_XOPEN_SOURCE=700 ou similaire sur la ligne de commande ou l'équivalent #define dans le code source.

Pour le meilleur ou le pire, j'utiliser un en-tête homebrew posixver.h:

/* 
@(#)File:   $RCSfile: posixver.h,v $ 
@(#)Version:  $Revision: 1.4 $ 
@(#)Last changed: $Date: 2017/06/18 00:15:42 $ 
@(#)Purpose:  Request appropriate POSIX and X/Open Support 
@(#)Author:   J Leffler 
@(#)Copyright:  (C) JLSS 2010-2017 
*/ 

/*TABSTOP=4*/ 

#ifndef JLSS_ID_POSIXVER_H 
#define JLSS_ID_POSIXVER_H 

/* 
** Include this file before including system headers. By default, with 
** C99 support from the compiler, it requests POSIX 2008 support. With 
** C89 support only, it requests POSIX 1997 support. Override the 
** default behaviour by setting either _XOPEN_SOURCE or _POSIX_C_SOURCE. 
*/ 

/* _XOPEN_SOURCE 700 is loosely equivalent to _POSIX_C_SOURCE 200809L */ 
/* _XOPEN_SOURCE 600 is loosely equivalent to _POSIX_C_SOURCE 200112L */ 
/* _XOPEN_SOURCE 500 is loosely equivalent to _POSIX_C_SOURCE 199506L */ 

#if !defined(_XOPEN_SOURCE) && !defined(_POSIX_C_SOURCE) 
#if defined(__cplusplus) 
#define _XOPEN_SOURCE 700 /* SUS v4, POSIX 1003.1 2008/13 (POSIX 2008/13) */ 
#elif __STDC_VERSION__ >= 199901L 
#define _XOPEN_SOURCE 700 /* SUS v4, POSIX 1003.1 2008/13 (POSIX 2008/13) */ 
#else 
#define _XOPEN_SOURCE 500 /* SUS v2, POSIX 1003.1 1997 */ 
#endif /* __STDC_VERSION__ */ 
#endif /* !_XOPEN_SOURCE && !_POSIX_C_SOURCE */ 

#endif /* JLSS_ID_POSIXVER_H */ 

Vous pouvez l'utiliser si vous le souhaitez, avec ou sans attribution. Vous pouvez trouver une version du fichier au https://github.com/jleffler/soq/tree/master/src/libsoq.