Storage Size of addrinfo isn't known - c

I am writing a simple network program in C. When I turned on -Wall with --std=c11, I got an error message about the way am declaring a struct.
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
int main() {
struct addrinfo res;
return 0;
}
The type addrinfo is defined in the sys/types.h file. I don't get an error when using a pointer.
How can I resolve this error message?
simple.c:9:25: error: storage size of ‘res’ isn’t known
struct addrinfo res;
^

Several points:
The type addrinfo is actually defined in netdb.h.
You can use the -E flag to gcc to see the pre-processor output and discover that the addrinfo structure is actually not defined in your code. Now you should suspect that probably some definition is missing.
As can be seen here, in order to expose the definition you need to use the _POSIX_C_SOURCE feature test macro.
So, this should resolve the mentioned error message:
#define _POSIX_C_SOURCE 200112L
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
int main() {
struct addrinfo res;
return 0;
}

Related

Typedeffing a function pointer seems to be local to just one header file

I'm trying to write a webserver in C, and I have a header file called route.h. Inside route.h I have the line typedef void (*RouteHandler)(struct HTTPRequest *, struct HTTPResponse *); which I believe creates the typedef RouteHandler which is a function that returns nothing, and takes two pointers to structs as arguments. Also inside route.h is this struct:
struct RouteTableEntry {
enum HTTPMethod method;
char *route;
RouteHandler handler;
};
This code compiles just fine, however when I try and use the typedef in a different header, server.h, I get the compiler error: server.h:27:8: error: unknown type name ‘RouteHandler’.
Here is my code:
route.h
#ifndef ROUTE_H_GUARD_
#define ROUTE_H_GUARD_
#include <stdlib.h>
#include "http.h"
#include "server.h"
typedef void (*RouteHandler)(struct HTTPRequest *, struct HTTPResponse *);
struct RouteTableEntry {
enum HTTPMethod method;
char *route;
RouteHandler handler;
};
...
#endif
server.h
#ifndef SERVER_H_GUARD_
#define SERVER_H_GUARD_
#include <stdint.h>
#include <stdio.h>
#include <sys/socket.h>
#include <unistd.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#include <pthread.h>
#include "http.h"
#include "route.h"
...
extern RouteHandler get_handler(enum HTTPMethod method, char *route, RouteHandler handler);
...
#endif
(I've reduced the code to just the relevant parts - if the full thing is necessary I will post the rest)
Your route.h itself includes server.h, and this before the beginning of the scope of the typedef. It is while processing that inclusion of server.h that the compiler complains, rightly, that there is no declaration of type RouteHandler in scope.
If indeed route.h and server.h each require something that the other declares then it is time to refactor. You haven't provided enough details for us to offer specific suggestions, but the kind of circular dependency you presently have will cause you continuing grief.
On the other hand, if route.h actually doesn't need anything from server.h then it ought not to be including it.

Getting error unknown type name 'size_t' even though I've included the relevant C libraries and headers

Please find my code below.
I am getting the error "/usr/include/linux/sysctl.h:40:2: error: unknown type name ‘size_t’"
Searching online, the only suggestion is to make sure you have stddef.h included in your code, which I do as can be seem below. There does not appear to be a solution available outside of this fix, which I have tried, so I am currently at a loss as to how to move forward.
Also note, this code is not pretty, but that is not the main issue with this thread. The error I am getting does not look like it is being thrown from a mistake in my code, but I may be wrong.
#include <linux/netfilter_ipv4.h>
#include <linux/netfilter.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <sys/types.h>
#include <linux/module.h>
#include <stddef.h>
struct nf_hook_ops{
struct list_head *list;
nf_hookfn *hook;
struct module *owner;
u_int8_t pf;
unsigned int hooknum;
int priority; /* Hooks are ordered in ascending priority. */
};
int nf_register_hook(struct nf_hook_ops *reg);
void nf_unregister_hook(struct nf_hook_ops *reg);
struct nf_hook_ops nfho = {
nfho.hook = hook_func_in,
nfho.hooknum = NF_INET_LOCAL_IN,
nfho.pf = PF_INE,
nfho.priority = NF_IP_PRI_FIRST
};
nf_register_hook(&nfho); // Register the hook
C is parsed strictly top to bottom, and #include does plain old textual inclusion, not anything clever that would qualify for the name of "module import". Therefore, the order of #include directives can matter. In this case, you're getting complaints about a type defined by stddef.h, so you must make sure that stddef.h is included before whatever needs it, which could be (indeed, is) another header file.
I can reproduce the error you're getting with the following two-line source file:
#include <linux/sysctl.h>
#include <stddef.h>
→
$ gcc -fsyntax-only test.c
In file included from test.c:1:0:
/usr/include/linux/sysctl.h:39:2: error: unknown type name ‘size_t’
If I exchange the order of the #include lines,
#include <stddef.h>
#include <linux/sysctl.h>
then there is no error. This is a bug in linux/sysctl.h, but I would not hold my breath for it to be fixed. I recommend moving stddef.h to the very top of the include list.
I can not reproduce the problem with your actual list of includes,
#include <linux/netfilter_ipv4.h>
#include <linux/netfilter.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <sys/types.h>
#include <linux/module.h>
#include <stddef.h>
but a gcc -H dump does not show linux/sysctl.h getting pulled in transitively by that set of includes, so probably it's just that I have a different version of the kernel headers on my Linux box than you do.

gcc compile time type resolution

I have three files, say A.c , B.c and C.c, all of which #include common.h
In common.h, I include "sys/socket.h" and I protect the common.h by macros:
#ifndef __COMMON_H
#define __COMMON_H
// body of file goes here
#endif
When i compile the code, I get several errors such as below
In file included from /usr/include/sys/socket.h:40,
from tcpperf.h:4,
from wrapunix.c:1:
/usr/include/bits/socket.h:425: error: conflicting types for 'recvmmsg'
/usr/include/bits/socket.h:425: note: previous declaration of 'recvmmsg' was here
In file included from /usr/include/sys/socket.h:40,
from tcpperf.h:4,
from wrapsock.c:1:
As you can see wrapunix.c and wrapsock.c, they both include tcpperf.h, but tcpperf.h is guarded with macros,yet gcc complains that recvmsg was declared multiple times. How do I resolve this issue?
Update:
Here is the header of tcpperf.h, that is causing issues
#ifndef _TCPPERF_H
#define _TCPPERF_H
#include <sys/types.h>
#include <sys/socket.h>
#include <time.h>
#include <regex.h>
#include <errno.h>
#include <sched.h>
#include <pthread.h>
#include <argp.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <linux/tcp.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <sys/prctl.h>
#include <unistd.h>
#include <sys/wait.h>
#endif
The above error can be reproduced by providing "-combine -fwhole-program" flags to gcc such as
gcc -std=gnu99 -Wall -combine -fwhole-program -I. error.c wrapunix.c wrapsock.c file1.c file2.c -o file2 -lrt
The error is "conflicting types for 'recvmmsg'" rather than just duplicate definition (which would be tolerated if equal). That means your .c source receives two different version of recvmmsg: one by your direct tcpperf.h inclusion and another one by inclusion it via sys/socket.h. I believe you have another version of tcpperf.h elsewhere in inclusion path with different (perhaps older version) recvmmsg.
The problem is almost certainly related to -combine. This is a bit of a guess, but in looking at the definition of recvmmsg:
extern int recvmmsg (int __fd, struct mmsghdr *__vmessages,
unsigned int __vlen, int __flags,
__const struct timespec *__tmo);
note that it takes a struct mmsghdr as an argument. However, while this prototype is unconditional, struct mmsghdr is only defined if __USE_GNU is set:
#ifdef __USE_GNU
/* For `recvmmsg'. */
struct mmsghdr
{
struct msghdr msg_hdr; /* Actual message header. */
unsigned int msg_len; /* Number of received bytes for the entry. */
};
#endif
-combine is basically equivalent to concatenating all your files together and then compiling them. Is there any chance that between the text of wrapunix.c and wrapsock.c that GNU_SOURCE is being defined? If that happened, then the first definition of recvmmsg would use a definition of struct mmsghdr that was local to just the prototype, while the second definition would use the real struct. Those two definitions would then be incompatible, which would result in the error message that you got.

Use of resolv.h

I'm trying to find out my DNS server address by reading it from resolv.h's _res struct. According to man 3 resolver the setup code should be.
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>
extern struct state _res;
and then I just read out whatever I need. My problem is that trying to compile this I get
resolver.c:5:21: error: conflicting types for '__res_state'
extern struct state _res;
^
/usr/include/resolv.h:251:16: note: expanded from macro '_res'
#define _res (*__res_state())
^
/usr/include/resolv.h:249:28: note: previous declaration is here
extern struct __res_state *__res_state(void) __attribute__ ((__const__));
^
1 error generated.
by clang.
What am I doing wrong?
You shouldn't declare _res yourself - resolv.h includes the right declaration (despite what the man page implies).
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>
int main() {
// call this first
res_init();
// do something with this list it contains list of dns servers
_res.nsaddr_list[0];
}

‘sockaddr_in6_t’ undeclared error even after inclusing the header files

I have following simple piece of code, which is a part of ipv6 handling module in a big project.
#include <ctype.h>
#include <sys/select.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <net/if.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/stat.h>
int main(){
sockaddr_in6_t* pSadrIn6 = (sockaddr_in6_t*) malloc(sizeof sockaddr_in6_t);
return 0;
}
It gives me following not error:
error: ‘sockaddr_in6_t’ undeclared (first use in this function)
Is there any special library installation or linking that I need to access the library?
It looks like you copied this code from the Linux IPv6 HOWTO but didn't copy the additional typedefs:
/*
** Type definitions (for convenience).
*/
typedef enum { false = 0, true } boolean;
typedef struct sockaddr_in sockaddr_in_t;
typedef struct sockaddr_in6 sockaddr_in6_t;
Personally I would just use the types as they are (instead of extra typedefs to avoid typing struct), but whatever

Resources