[Freeciv-Dev] Re: (PR#7121) casting sockaddr and sockaddr_in
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
<URL: http://rt.freeciv.org/Ticket/Display.html?id=7121 >
On Sat, Jan 10, 2004 at 03:02:27AM -0800, Raimar Falke wrote:
>
> <URL: http://rt.freeciv.org/Ticket/Display.html?id=7121 >
>
> On Fri, Dec 19, 2003 at 12:30:22PM -0800, Brett Albertson wrote:
> >
> > <URL: http://rt.freeciv.org/Ticket/Display.html?id=7121 >
> >
> > During compilation of the current CVS code, I get this on Solaris 9:
> >
> > if gcc -DHAVE_CONFIG_H -I. -I. -I.. -I../intl -I./aicore -g -O2
> > -Werror -Wall -Wpointer-arith -Wcast-align -Wmissing-prototypes
> > -Wmissing-declarations -MT netintf.o -MD -MP -MF ".deps/netintf.Tpo" -c
> > -o netintf.o netintf.c; \
> > then mv -f ".deps/netintf.Tpo" ".deps/netintf.Po"; else rm -f
> > ".deps/netintf.Tpo"; exit 1; fi
> > netintf.c: In function `net_lookup_service':
> > netintf.c:175: warning: cast increases required alignment of target type
> > make[3]: *** [netintf.o] Error 1
> > make[3]: Leaving directory `/var/tmp/freeciv/common'
> > make[2]: *** [all-recursive] Error 1
> > make[2]: Leaving directory `/var/tmp/freeciv/common'
> > make[1]: *** [all-recursive] Error 1
> > make[1]: Leaving directory `/var/tmp/freeciv'
> > make: *** [all] Error 2
> >
> >
> > This is due to the following line:
> >
> > sock = (struct sockaddr_in *) sa;
> >
> > In the code, sa is declared as:
> >
> > struct sockaddr *sa
> >
> > I think casting sockaddr to a sockaddr_in type in Solaris is a bad
> > thing. I'm not sure how to fix it.
>
> Tricky. Options:
> - change all struct sockaddr to struct sockaddr_in in the function
> prototypes (no IPv6 support)
> - copy the data:
> struct sockaddr _sa=*sa;
> struct sockaddr_in _sock;
> assert(sizeof(_sa)==sizeof(_sock));
> memcpy(_sock,_sa,sizeof(_sa));
> sock=&_sock;
> - create a new union type
> union {
> struct sockaddr addr;
> struct sockaddr_in addr_in;
> } my_sock_addr;
> and pass this union type around. Because of the union the pointer
> will have to correct alignment.
> - ignore it
> - cast it away with a cast to "void *".
>
> Note that this is a real error for CPUs which have real alignment
> rules (i386 doesn't have these) AND the "struct sockaddr *" producer
> chooses the weaker alignment of struct sockaddr and so doesn't satisfy
> the alignment requirements of struct sockaddr_in.
>
> The union approach is the most clean one. We should do it.
Here is the patch for the union approach. Please test.
Raimar
--
email: rf13@xxxxxxxxxxxxxxxxx
"The primary purpose of the DATA statement is to give names to
constants; instead of referring to pi as 3.141592653589793 at every
appearance, the variable PI can be given that value with a DATA
statement and used instead of the longer form of the constant. This
also simplifies modifying the program, should the value of pi
change."
-- FORTRAN manual for Xerox Computers
Index: client/clinet.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/clinet.c,v
retrieving revision 1.93
diff -u -u -r1.93 clinet.c
--- client/clinet.c 2004/01/05 00:18:29 1.93
+++ client/clinet.c 2004/01/11 19:23:03
@@ -89,7 +89,7 @@
struct connection aconnection;
static int socklan;
static struct server_list *lan_servers;
-static struct sockaddr_in server_addr;
+static union my_sockaddr server_addr;
/**************************************************************************
Close socket and cleanup. This one doesn't print a message, so should
@@ -154,8 +154,7 @@
if (!hostname)
hostname = "localhost";
- if (!net_lookup_service(hostname, port, (struct sockaddr *)&server_addr,
- sizeof(server_addr))) {
+ if (!net_lookup_service(hostname, port, &server_addr)) {
(void) mystrlcpy(errbuf, _("Failed looking up host."), errbufsize);
return -1;
}
@@ -189,7 +188,7 @@
return -1;
}
- if (connect(aconnection.sock, (struct sockaddr *) &server_addr,
+ if (connect(aconnection.sock, &server_addr.sockaddr,
sizeof(server_addr)) == -1) {
(void) mystrlcpy(errbuf, mystrerror(errno), errbufsize);
my_closesocket(aconnection.sock);
@@ -493,7 +492,7 @@
struct server_list *create_server_list(char *errbuf, int n_errbuf)
{
struct server_list *server_list;
- struct sockaddr_in addr;
+ union my_sockaddr addr;
int s;
fz_FILE *f;
char *proxy_url;
@@ -554,7 +553,7 @@
urlpath = s;
}
- if (!net_lookup_service(server,port,(struct sockaddr *) &addr,sizeof(addr)))
{
+ if (!net_lookup_service(server, port, &addr)) {
(void) mystrlcpy(errbuf, _("Failed looking up host"), n_errbuf);
return NULL;
}
@@ -564,7 +563,7 @@
return NULL;
}
- if(connect(s, (struct sockaddr *) &addr, sizeof (addr)) == -1) {
+ if(connect(s, &addr.sockaddr, sizeof (addr)) == -1) {
(void) mystrlcpy(errbuf, mystrerror(errno), n_errbuf);
my_closesocket(s);
return NULL;
@@ -668,7 +667,7 @@
**************************************************************************/
int begin_lanserver_scan(void)
{
- struct sockaddr_in addr;
+ union my_sockaddr addr;
struct data_out dout;
int sock, opt = 1;
unsigned char buffer[MAX_LEN_PACKET];
@@ -691,9 +690,9 @@
/* Set the UDP Multicast group IP address. */
group = get_multicast_group();
memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = inet_addr(get_multicast_group());
- addr.sin_port = htons(SERVER_LAN_PORT);
+ addr.sockaddr_in.sin_family = AF_INET;
+ addr.sockaddr_in.sin_addr.s_addr = inet_addr(get_multicast_group());
+ addr.sockaddr_in.sin_port = htons(SERVER_LAN_PORT);
/* Set the Time-to-Live field for the packet */
ttl = SERVER_LAN_TTL;
@@ -714,7 +713,7 @@
size = dio_output_used(&dout);
- if (sendto(sock, buffer, size, 0, (struct sockaddr *) &addr,
+ if (sendto(sock, buffer, size, 0, &addr.sockaddr,
sizeof(addr)) < 0) {
freelog(LOG_ERROR, "sendto failed: %s", mystrerror(errno));
return 0;
@@ -738,11 +737,11 @@
}
memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = htonl(INADDR_ANY);
- addr.sin_port = htons(SERVER_LAN_PORT + 1);
+ addr.sockaddr_in.sin_family = AF_INET;
+ addr.sockaddr_in.sin_addr.s_addr = htonl(INADDR_ANY);
+ addr.sockaddr_in.sin_port = htons(SERVER_LAN_PORT + 1);
- if (bind(socklan, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ if (bind(socklan, &addr.sockaddr, sizeof(addr)) < 0) {
freelog(LOG_ERROR, "bind failed: %s", mystrerror(errno));
return 0;
}
@@ -772,7 +771,7 @@
# else
int fromlen;
# endif
- struct sockaddr_in fromend;
+ union my_sockaddr fromend;
struct hostent *from;
char msgbuf[128];
int type;
@@ -806,7 +805,7 @@
/* Try to receive a packet from a server. */
if (0 < recvfrom(socklan, msgbuf, sizeof(msgbuf), 0,
- (struct sockaddr *) &fromend, &fromlen)) {
+ &fromend.sockaddr, &fromlen)) {
struct server *pserver;
dio_get_uint8(&din, &type);
@@ -821,9 +820,9 @@
dio_get_string(&din, metastring, sizeof(metastring));
if (!mystrcasecmp("none", servername)) {
- from = gethostbyaddr((char *)&fromend.sin_addr,
- sizeof(fromend.sin_addr), AF_INET);
- sz_strlcpy(servername, inet_ntoa(fromend.sin_addr));
+ from = gethostbyaddr((char *) &fromend.sockaddr_in.sin_addr,
+ sizeof(fromend.sockaddr_in.sin_addr), AF_INET);
+ sz_strlcpy(servername, inet_ntoa(fromend.sockaddr_in.sin_addr));
}
/* UDP can send duplicate or delayed packets. */
Index: common/netintf.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/netintf.c,v
retrieving revision 1.18
diff -u -u -r1.18 netintf.c
--- common/netintf.c 2003/11/19 11:16:52 1.18
+++ common/netintf.c 2004/01/11 19:23:14
@@ -163,16 +163,11 @@
/***************************************************************************
Look up the service at hostname:port and fill in *sa.
***************************************************************************/
-bool net_lookup_service(const char *name,int port,struct sockaddr *sa,int len)
+bool net_lookup_service(const char *name, int port, union my_sockaddr *addr)
{
struct hostent *hp;
- struct sockaddr_in *sock = NULL;
+ struct sockaddr_in *sock = &addr->sockaddr_in;
- if (len != sizeof(*sock)) {
- return FALSE;
- }
-
- sock = (struct sockaddr_in *) sa;
sock->sin_family = AF_INET;
sock->sin_port = htons(port);
Index: common/netintf.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/netintf.h,v
retrieving revision 1.8
diff -u -u -r1.8 netintf.h
--- common/netintf.h 2003/04/04 15:47:49 1.8
+++ common/netintf.h 2004/01/11 19:23:14
@@ -43,7 +43,10 @@
#define MY_FD_ZERO(p) memset((void *)(p), 0, sizeof(*(p)))
#endif
-struct sockaddr;
+union my_sockaddr {
+ struct sockaddr sockaddr;
+ struct sockaddr_in sockaddr_in;
+};
int my_readsocket(int sock, void *buf, size_t size);
int my_writesocket(int sock, const void *buf, size_t size);
@@ -53,7 +56,7 @@
void my_nonblock(int sockfd);
bool net_lookup_service(const char *name, int port,
- struct sockaddr *sa, int len);
+ union my_sockaddr *addr);
fz_FILE *my_querysocket(int sock, void *buf, size_t size);
#endif /* FC__NETINTF_H */
Index: server/meta.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/meta.c,v
retrieving revision 1.58
diff -u -u -r1.58 meta.c
--- server/meta.c 2003/11/19 11:16:52 1.58
+++ server/meta.c 2004/01/11 19:23:32
@@ -73,7 +73,7 @@
bool server_is_open = FALSE;
static int sockfd=0;
-static struct sockaddr_in meta_addr;
+static union my_sockaddr meta_addr;
/*************************************************************************
@@ -181,7 +181,7 @@
{
char *metaname = srvarg.metaserver_addr;
int metaport;
- struct sockaddr_in bind_addr;
+ union my_sockaddr bind_addr;
/*
* Fill in the structure "meta_addr" with the address of the
@@ -189,8 +189,7 @@
* is valid, both decimal-dotted and name.
*/
metaport = srvarg.metaserver_port;
- if (!net_lookup_service(metaname, metaport, (struct sockaddr *) &meta_addr,
- sizeof(meta_addr))) {
+ if (!net_lookup_service(metaname, metaport, &meta_addr)) {
freelog(LOG_ERROR, _("Metaserver: bad address: [%s:%d]."),
metaname,
metaport);
@@ -212,23 +211,21 @@
* Bind any local address for us and
* associate datagram socket with server.
*/
- if (!net_lookup_service(srvarg.bind_addr, 0,
- (struct sockaddr *) &bind_addr,
- sizeof(bind_addr))) {
+ if (!net_lookup_service(srvarg.bind_addr, 0, &bind_addr)) {
freelog(LOG_ERROR, _("Metaserver: bad address: [%s:%d]."),
srvarg.bind_addr, 0);
metaserver_failed();
}
/* set source IP */
- if (bind(sockfd, (struct sockaddr *) &bind_addr, sizeof(bind_addr)) == -1) {
+ if (bind(sockfd, &bind_addr.sockaddr, sizeof(bind_addr)) == -1) {
freelog(LOG_ERROR, "Metaserver: bind failed: %s", mystrerror(errno));
metaserver_failed();
return;
}
/* no, this is not weird, see man connect(2) --vasc */
- if (connect(sockfd, (struct sockaddr *) &meta_addr, sizeof(meta_addr))==-1) {
+ if (connect(sockfd, &meta_addr.sockaddr, sizeof(meta_addr))==-1) {
freelog(LOG_ERROR, "Metaserver: connect failed: %s", mystrerror(errno));
metaserver_failed();
return;
Index: server/sernet.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/sernet.c,v
retrieving revision 1.112
diff -u -u -r1.112 sernet.c
--- server/sernet.c 2003/11/28 17:37:22 1.112
+++ server/sernet.c 2004/01/11 19:23:35
@@ -700,21 +700,22 @@
# endif
int new_sock;
- struct sockaddr_in fromend;
+ union my_sockaddr fromend;
struct hostent *from;
int i;
fromlen = sizeof(fromend);
- if ((new_sock=accept(sockfd, (struct sockaddr *) &fromend, &fromlen)) == -1)
{
+ if ((new_sock = accept(sockfd, &fromend.sockaddr, &fromlen)) == -1) {
freelog(LOG_ERROR, "accept failed: %s", mystrerror(errno));
return -1;
}
my_nonblock(new_sock);
- from=gethostbyaddr((char *)&fromend.sin_addr, sizeof(fromend.sin_addr),
- AF_INET);
+ from =
+ gethostbyaddr((char *) &fromend.sockaddr_in.sin_addr,
+ sizeof(fromend.sockaddr_in.sin_addr), AF_INET);
for(i=0; i<MAX_NUM_CONNECTIONS; i++) {
struct connection *pconn = &connections[i];
@@ -740,7 +741,8 @@
sz_strlcpy(pconn->username, makeup_connection_name(&pconn->id));
sz_strlcpy(pconn->addr,
- (from ? from->h_name : inet_ntoa(fromend.sin_addr)));
+ (from ? from->
+ h_name : inet_ntoa(fromend.sockaddr_in.sin_addr)));
conn_list_insert_back(&game.all_connections, pconn);
@@ -762,8 +764,8 @@
int server_open_socket(void)
{
/* setup socket address */
- struct sockaddr_in src;
- struct sockaddr_in addr;
+ union my_sockaddr src;
+ union my_sockaddr addr;
struct ip_mreq mreq;
const char *group;
int opt;
@@ -779,15 +781,13 @@
freelog(LOG_ERROR, "SO_REUSEADDR failed: %s", mystrerror(errno));
}
- if (!net_lookup_service
- (srvarg.bind_addr, srvarg.port, (struct sockaddr *) &src,
- sizeof(src))) {
+ if (!net_lookup_service(srvarg.bind_addr, srvarg.port, &src)) {
freelog(LOG_ERROR, _("Server: bad address: [%s:%d]."),
srvarg.bind_addr, srvarg.port);
exit(EXIT_FAILURE);
}
- if(bind(sock, (struct sockaddr *) &src, sizeof (src)) == -1) {
+ if(bind(sock, &src.sockaddr, sizeof (src)) == -1) {
freelog(LOG_FATAL, "bind failed: %s", mystrerror(errno));
exit(EXIT_FAILURE);
}
@@ -812,11 +812,11 @@
group = get_multicast_group();
memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = htonl(INADDR_ANY);
- addr.sin_port = htons(SERVER_LAN_PORT);
+ addr.sockaddr_in.sin_family = AF_INET;
+ addr.sockaddr_in.sin_addr.s_addr = htonl(INADDR_ANY);
+ addr.sockaddr_in.sin_port = htons(SERVER_LAN_PORT);
- if (bind(socklan, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ if (bind(socklan, &addr.sockaddr, sizeof(addr)) < 0) {
freelog(LOG_ERROR, "bind failed: %s", mystrerror(errno));
}
@@ -1002,7 +1002,7 @@
unsigned char players[256];
unsigned char status[256];
struct data_out dout;
- struct sockaddr_in addr;
+ union my_sockaddr addr;
int socksend, setting = 1;
const char *group;
size_t size;
@@ -1017,9 +1017,9 @@
/* Set the UDP Multicast group IP address of the packet. */
group = get_multicast_group();
memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = inet_addr(group);
- addr.sin_port = htons(SERVER_LAN_PORT + 1);
+ addr.sockaddr_in.sin_family = AF_INET;
+ addr.sockaddr_in.sin_addr.s_addr = inet_addr(group);
+ addr.sockaddr_in.sin_port = htons(SERVER_LAN_PORT + 1);
/* Set the Time-to-Live field for the packet. */
ttl = SERVER_LAN_TTL;
@@ -1073,7 +1073,7 @@
size = dio_output_used(&dout);
/* Sending packet to client with the information gathered above. */
- if (sendto(socksend, buffer, size, 0, (struct sockaddr *)&addr,
+ if (sendto(socksend, buffer, size, 0, &addr.sockaddr,
sizeof(addr)) < 0) {
freelog(LOG_ERROR, "sendto failed: %s", mystrerror(errno));
return;
|
|