Hi Naveen,

On pe, 2015-10-02 at 10:20 -0700, Naveen Singh wrote:
> Hi Jukka,
> 
> On Fri, Oct 2, 2015 at 12:29 AM, Jukka Rissanen
> <[email protected]> wrote:
>         Hi Naveen,
>         
>         On to, 2015-10-01 at 23:00 -0700, Naveen Singh wrote:
>         > On Thu, Oct 1, 2015 at 6:26 AM, Patrik Flykt
>         <[email protected]>
>         > wrote:
>         >
>         > >
>         > >         Hi,
>         > >
>         > > On Wed, 2015-09-30 at 22:08 -0700, Naveen Singh wrote:
>         > > > From: Naveen Singh <[email protected]>
>         > > >
>         > > > Current NTP code is written with an assumption that
>         timeserver is
>         > > > always an IPv4 address. If there is an IPv6 timeserver
>         then the socket
>         > > > operation would fail with error as Permission denied
>         (13). This change in
>         > > > ntp.c ensures that code works fine with both IPv4 and
>         IPv6 address.
>         > > > ---
>         > > >  src/ntp.c | 129
>         > >
>         ++++++++++++++++++++++++++++++++++++++++++++++++--------------
>         > > >  1 file changed, 101 insertions(+), 28 deletions(-)
>         > >
>         > > This was patch version 2, so the next one is version 3.
>         Add the version
>         > > to the Subject: line as [PATCH v3], this can be done with
>         > > 'git ... --subject-prefix="PATCH v3" ...'.
>         > >
>         > > > diff --git a/src/ntp.c b/src/ntp.c
>         > > > index 2c313a4..a55365d 100644
>         > > > --- a/src/ntp.c
>         > > > +++ b/src/ntp.c
>         > > > @@ -18,7 +18,6 @@
>         > > >   *  Foundation, Inc., 51 Franklin St, Fifth Floor,
>         Boston, MA
>         > > 02110-1301  USA
>         > > >   *
>         > > >   */
>         > > > -
>         > > >  #ifdef HAVE_CONFIG_H
>         > > >  #include <config.h>
>         > > >  #endif
>         > > > @@ -34,6 +33,7 @@
>         > > >  #include <netinet/in.h>
>         > > >  #include <netinet/ip.h>
>         > > >  #include <arpa/inet.h>
>         > > > +#include <netdb.h>
>         > > >
>         > > >  #include <glib.h>
>         > > >
>         > > > @@ -117,12 +117,12 @@ static struct timespec mtx_time;
>         > > >  static int transmit_fd = 0;
>         > > >
>         > > >  static char *timeserver = NULL;
>         > > > -static struct sockaddr_in timeserver_addr;
>         > > > +static struct sockaddr_storage timeserver_addr;
>         > > >  static gint poll_id = 0;
>         > > >  static gint timeout_id = 0;
>         > > >  static guint retries = 0;
>         > > >
>         > > > -static void send_packet(int fd, const char *server,
>         uint32_t timeout);
>         > > > +static void send_packet(int fd, const char *server,
>         uint32_t timeout,
>         > > int family);
>         > > >
>         > > >  static void next_server(void)
>         > > >  {
>         > > > @@ -143,17 +143,21 @@ static gboolean
>         send_timeout(gpointer user_data)
>         > > >       if (retries++ == NTP_SEND_RETRIES)
>         > > >               next_server();
>         > > >       else
>         > > > -             send_packet(transmit_fd, timeserver,
>         timeout << 1);
>         > > > +             send_packet(transmit_fd, timeserver,
>         timeout << 1,
>         > > timeserver_addr.ss_family);
>         > > >
>         > > >       return FALSE;
>         > > >  }
>         > > >
>         > > > -static void send_packet(int fd, const char *server,
>         uint32_t timeout)
>         > > > +static void send_packet(int fd, const char *server,
>         uint32_t timeout,
>         > > int family)
>         > >
>         > > Instead of supplying a char *server, why don't we give a
>         struct
>         > > sockaddr* instead? What's the purpose of carrying the
>         server
>         > > "name" (nah, the IP address as a string), if it is already
>         resolved in
>         > > the calling function? BTW, it is available as
>         timeserver_addr, so do we
>         > > really need any of this information here?
>         > >
>         >
>         > Yes it makes sense but I am not sure sockaddr * is the one
>         we should us. It
>         > will not be able to hold IPv6 address which is 16 bytes. So
>         I guess
>         > sockaddr_storage* would be the right thing. Do you agree? If
>         you look i
>         > changed type of timeserver_addr to sockaddr_storage. Do you
>         agree with this?
>         >
>         > /* Structure describing a generic socket address.  */
>         > struct sockaddr
>         >   {
>         >     __SOCKADDR_COMMON (sa_);    /* Common data: address
>         family and length.
>         >  */
>         >     char sa_data[14];           /* Address data.  */
>         >   };
>         >
>         >
>         
>         
>         You should never instantiate (== have a variable "struct
>         sockaddr
>         myaddr") because there is not enough space as you noticed. You
>         either
>         have a "struct sockaddr_in myaddr" or "struct sockaddr_in6
>         myaddr" and
>         then you just cast "struct sockaddr *" to correct variable.
>         There is no need to use sockaddr_storage here.
> 
> 
> Exactly this is what I am saying.My concern is for the type of
> timeserver_addr which is used for storing the IP address of the
> server. It cannot be sockaddr. It needs to be sockaddr_storage. Where
> we know what IP address we are using we can use sockaddr_in or
> sockaddr_in6 and hen cast it to sockaddr *. 


Normally in socket programming you instantiate either sockaddr_in or
sockaddr_in6 variable, and then cast sockaddr * to that variable and
pass that pointer around. At least I would prefer that way instead of
creating sockaddr_storage variable for this purpose. So in practice
there is no need to create sockaddr_storage variable.


> 
> 
> Does this make sense? Do you agree?
>         
>         >
>         > > >  {
>         > > >       struct ntp_msg msg;
>         > > > -     struct sockaddr_in addr;
>         > > > +     struct sockaddr_in in4addr;
>         > > > +     struct sockaddr_in6 in6addr;
>         > > > +     struct sockaddr * addr;
>         > > >       struct timeval transmit_timeval;
>         > > >       ssize_t len;
>         > > > +     int size;
>         > > > +     unsigned char * addrptr;
>         > > >
>         > > >       /*
>         > > >        * At some point, we could specify the actual
>         system precision
>         > > with:
>         > > > @@ -168,10 +172,29 @@ static void send_packet(int fd,
>         const char
>         > > *server, uint32_t timeout)
>         > > >       msg.poll = 10;  // max
>         > > >       msg.precision = NTP_PRECISION_S;
>         > > >
>         > > > -     memset(&addr, 0, sizeof(addr));
>         > > > -     addr.sin_family = AF_INET;
>         > > > -     addr.sin_port = htons(123);
>         > > > -     addr.sin_addr.s_addr = inet_addr(server);
>         > > > +     if (family == AF_INET) {
>         > > > +             memset(&in4addr, 0, sizeof(in4addr));
>         > > > +             in4addr.sin_family = AF_INET;
>         > > > +             in4addr.sin_port = htons(123);
>         > > > +             size = sizeof(in4addr);
>         > > > +             addrptr = (unsigned char
>         *)&in4addr.sin_addr.s_addr;
>         > > > +             addr = (struct sockaddr *)&in4addr;
>         > > > +     } else if (family == AF_INET6){
>         > > > +             memset(&in6addr, 0, sizeof(in6addr));
>         > > > +             in6addr.sin6_family = AF_INET6;
>         > > > +             in6addr.sin6_port = htons(123);
>         > > > +             size = sizeof(in6addr);
>         > > > +             addrptr =
>         in6addr.sin6_addr.__in6_u.__u6_addr8;
>         > > > +             addr = (struct sockaddr *)&in6addr;
>         > > > +     } else {
>         > > > +             DBG("wrong family type");
>         > > > +             return;
>         > > > +     }
>         > > > +     if (inet_pton(family, server, addrptr) == 0)
>         > > > +     {
>         > > > +             DBG("cannot convert ip address string");
>         > > > +             return;
>         > > > +     }
>         > >
>         > > The above is unnecessary. You already have timeserver_addr
>         set or the
>         > > function gets a sockaddr * to use.
>         > >
>         >
>         > Agreed. If we pass sockaddr_storage*.
>         
>         
>         No, sockaddr * is enough.
>         
>         >
>         > >
>         > > >       gettimeofday(&transmit_timeval, NULL);
>         > > >       clock_gettime(CLOCK_MONOTONIC, &mtx_time);
>         > > > @@ -180,7 +203,7 @@ static void send_packet(int fd,
>         const char *server,
>         > > uint32_t timeout)
>         > > >       msg.xmttime.fraction =
>         htonl(transmit_timeval.tv_usec * 1000);
>         > > >
>         > > >       len = sendto(fd, &msg, sizeof(msg), MSG_DONTWAIT,
>         > > > -                                             &addr,
>         sizeof(addr));
>         > > > +                                             addr,
>         size);
>         > >
>         > > Use the stored timeserver_addr or supplied sockaddr *
>         family information
>         > > to set the size to either sizeof(struct sockaddr_in) or
>         sizeof(struct
>         > > sockaddr_in6).
>         > >
>         > I guess this is what i am doing. But will double confirm.
>         >
>         > >
>         > > >       if (len < 0) {
>         > > >               connman_error("Time request for server %s
>         failed (%d/%s)",
>         > > >                       server, errno, strerror(errno));
>         > > > @@ -213,7 +236,7 @@ static gboolean next_poll(gpointer
>         user_data)
>         > > >       if (!timeserver || transmit_fd == 0)
>         > > >               return FALSE;
>         > > >
>         > > > -     send_packet(transmit_fd, timeserver,
>         NTP_SEND_TIMEOUT);
>         > > > +     send_packet(transmit_fd, timeserver,
>         NTP_SEND_TIMEOUT,
>         > > timeserver_addr.ss_family);
>         > > >
>         > > >       return FALSE;
>         > > >  }
>         > > > @@ -363,7 +386,7 @@ static gboolean
>         received_data(GIOChannel *channel,
>         > > GIOCondition condition,
>         > > >
>          gpointer user_data)
>         > > >  {
>         > > >       unsigned char buf[128];
>         > > > -     struct sockaddr_in sender_addr;
>         > > > +     struct sockaddr_storage sender_addr;
>         > > >       struct msghdr msg;
>         > > >       struct iovec iov;
>         > > >       struct cmsghdr *cmsg;
>         > > > @@ -396,9 +419,18 @@ static gboolean
>         received_data(GIOChannel *channel,
>         > > GIOCondition condition,
>         > > >       if (len < 0)
>         > > >               return TRUE;
>         > > >
>         > > > -     if (timeserver_addr.sin_addr.s_addr !=
>         sender_addr.sin_addr.s_addr)
>         > > > -             /* only accept messages from the
>         timeserver */
>         > > > +     if (sender_addr.ss_family == AF_INET) {
>         > > > +             if (((struct sockaddr_in
>         > > *)&timeserver_addr)->sin_addr.s_addr != ((struct
>         sockaddr_in
>         > > *)&sender_addr)->sin_addr.s_addr)
>         > > > +                     return TRUE;
>         > > > +     } else if(sender_addr.ss_family == AF_INET6) {
>         > > > +             if (memcmp(((struct sockaddr_in6
>         > > *)&timeserver_addr)->sin6_addr.__in6_u.__u6_addr8,
>         > > > +                                     ((struct
>         sockaddr_in6
>         > > *)&sender_addr)->sin6_addr.__in6_u.__u6_addr8,
>         > > > +                                     16) != 0)
>         > >
>         > > Use memcmp for both of these. First check address
>         families, if they
>         > > match the size can be deduced (for example as above) and
>         have only a
>         > > single memcmp to do the matching.
>         > >
>         > Agreed.
>         >
>         > >
>         > > > +                     return TRUE;
>         > > > +     } else {
>         > > > +             connman_error("Not a valid family type");
>         > > >               return TRUE;
>         > > > +        }
>         > > >
>         > > >       tv = NULL;
>         > > >       clock_gettime(CLOCK_MONOTONIC, &mrx_time);
>         > > > @@ -422,36 +454,78 @@ static gboolean
>         received_data(GIOChannel *channel,
>         > > GIOCondition condition,
>         > > >  static void start_ntp(char *server)
>         > > >  {
>         > > >       GIOChannel *channel;
>         > > > -     struct sockaddr_in addr;
>         > > > +     struct sockaddr * addr;
>         > > > +     struct sockaddr_in in4addr;
>         > > > +     struct sockaddr_in6 in6addr;
>         > > > +     struct addrinfo hint;
>         > > > +     struct addrinfo *info;
>         > > > +     int family;
>         > > >       int tos = IPTOS_LOWDELAY, timestamp = 1;
>         > > > +     int size;
>         > > > +     int ret;
>         > > >
>         > > >       if (!server)
>         > > >               return;
>         > > >
>         > > > -     DBG("server %s", server);
>         > > > +     memset(&hint, 0, sizeof(hint));
>         > > > +     hint.ai_family = AF_UNSPEC;
>         > > > +     hint.ai_flags = AI_NUMERICHOST;
>         > > > +     ret = getaddrinfo(server, NULL, &hint, &info);
>         > > > +
>         > > > +     if (ret) {
>         > > > +             connman_error("cannot get server info");
>         > > > +             return;
>         > > > +     }
>         > > > +
>         > > > +     family = info->ai_family;
>         > > > +     freeaddrinfo(info);
>         > >
>         > > Before throwing away info, the address is already
>         available as
>         > > ->sin6_addr or ->sin_addr. See man getaddrinfo. Store the
>         address and
>         > > the address family in timeserver_addr.
>         > >
>         > > I guess this may not be correct as getaddrinfo gives us a
>         pointer to
>         > sockaddr which may not be able to contain the 16 byte IPv6
>         address. Do you
>         > agree? I guess using inet_pton is the best way.
>         >
>         > > > +
>         > > > +     DBG("server %s family %d", server, family);
>         > > >
>         > > >       if (channel_watch > 0)
>         > > >               goto send;
>         > > >
>         > > > -     transmit_fd = socket(PF_INET, SOCK_DGRAM |
>         SOCK_CLOEXEC, 0);
>         > > > -     if (transmit_fd < 0) {
>         > > > +     transmit_fd = socket(family, SOCK_DGRAM |
>         SOCK_CLOEXEC, 0);
>         > > > +     if (transmit_fd <= 0) {
>         > > >               connman_error("Failed to open time server
>         socket");
>         > > >               return;
>         > > >       }
>         > > >
>         > > > -     memset(&addr, 0, sizeof(addr));
>         > > > -     addr.sin_family = AF_INET;
>         > > > +     if (family == AF_INET) {
>         > > > +             memset(&in4addr, 0, sizeof(in4addr));
>         > > > +             in4addr.sin_family = family;
>         > > > +             addr = (struct sockaddr *)&in4addr;
>         > > > +             size = sizeof(in4addr);
>         > > > +             if (inet_pton(family, server, &(((struct
>         sockaddr_in
>         > > *)&timeserver_addr)->sin_addr.s_addr)) == 0) {
>         > > > +                     DBG("cannot convert ipv4 address
>         string");
>         > > > +             }
>         > > > +     } else if (family == AF_INET6) {
>         > > > +             memset(&in6addr, 0, sizeof(in6addr));
>         > > > +             in6addr.sin6_family = family;
>         > > > +             addr = (struct sockaddr *)&in6addr;
>         > > > +             size = sizeof(in6addr);
>         > > > +             if (inet_pton(family, server, ((struct
>         sockaddr_in6
>         > > *)&timeserver_addr)->sin6_addr.__in6_u.__u6_addr8) == 0) {
>         > > > +                     DBG("cannot convert ipv6 address
>         string");
>         > > > +             }
>         > > > +     } else {
>         > > > +             connman_error("Family not correct");
>         > > > +             return;
>         > > > +     }
>         > >
>         > > No need for the above, look into the 'info' supplied to
>         getaddrinfo()
>         > > above.
>         > >
>         > > > -     if (bind(transmit_fd, (struct sockaddr *) &addr,
>         sizeof(addr)) <
>         > > 0) {
>         > > > +     timeserver_addr.ss_family = family;
>         > > > +
>         > > > +     if (bind(transmit_fd, (struct sockaddr *) addr,
>         size) < 0) {
>         > > >               connman_error("Failed to bind time server
>         socket");
>         > > >               close(transmit_fd);
>         > > >               return;
>         > > >       }
>         > > >
>         > > > -     if (setsockopt(transmit_fd, IPPROTO_IP, IP_TOS,
>         &tos, sizeof(tos))
>         > > < 0) {
>         > > > -             connman_error("Failed to set type of
>         service option");
>         > > > -             close(transmit_fd);
>         > > > -             return;
>         > > > +     if (family == AF_INET) {
>         > > > +             if (setsockopt(transmit_fd, IPPROTO_IP,
>         IP_TOS, &tos,
>         > > sizeof(tos)) < 0) {
>         > > > +                     connman_error("Failed to set type
>         of service
>         > > option");
>         > > > +                     close(transmit_fd);
>         > > > +                     return;
>         > > > +             }
>         > > >       }
>         > > >
>         > > >       if (setsockopt(transmit_fd, SOL_SOCKET,
>         SO_TIMESTAMP, &timestamp,
>         > > > @@ -479,7 +553,7 @@ static void start_ntp(char *server)
>         > > >       g_io_channel_unref(channel);
>         > > >
>         > > >  send:
>         > > > -     send_packet(transmit_fd, server,
>         NTP_SEND_TIMEOUT);
>         > > > +     send_packet(transmit_fd, server, NTP_SEND_TIMEOUT,
>         family);
>         > > >  }
>         > > >
>         > > >  int __connman_ntp_start(char *server)
>         > > > @@ -493,7 +567,6 @@ int __connman_ntp_start(char
>         *server)
>         > > >               g_free(timeserver);
>         > > >
>         > > >       timeserver = g_strdup(server);
>         > > > -     timeserver_addr.sin_addr.s_addr =
>         inet_addr(server);
>         > > >
>         > > >       start_ntp(timeserver);
>         > > >
>         > >
>         > >         Patrik
>         > >
>         > > Regards
>         > >
>         > Naveen
>         >
>         
>         
>         Cheers,
>         Jukka
>         
>         
> 
> 


_______________________________________________
connman mailing list
[email protected]
https://lists.connman.net/mailman/listinfo/connman

Reply via email to