Complete.Org: Mailing Lists: Archives: freeciv-dev: January 2004:
[Freeciv-Dev] Re: (PR#7121) casting sockaddr and sockaddr_in
Home

[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]
To: brett.albertson@xxxxxxxxxxxx
Subject: [Freeciv-Dev] Re: (PR#7121) casting sockaddr and sockaddr_in
From: "Raimar Falke" <i-freeciv-lists@xxxxxxxxxxxxx>
Date: Sun, 11 Jan 2004 11:34:33 -0800
Reply-to: rt@xxxxxxxxxxx

<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;

[Prev in Thread] Current Thread [Next in Thread]