dnsproxy: Randomize the transaction id
[framework/connectivity/connman.git] / src / inet.c
index 1fc636e..effa68c 100644 (file)
@@ -2,7 +2,7 @@
  *
  *  Connection Manager
  *
- *  Copyright (C) 2007-2010  Intel Corporation. All rights reserved.
+ *  Copyright (C) 2007-2012  Intel Corporation. All rights reserved.
  *  Copyright (C) 2003-2005  Go-Core Project
  *  Copyright (C) 2003-2006  Helsinki University of Technology
  *
@@ -44,6 +44,7 @@
 #include <netinet/icmp6.h>
 #include <fcntl.h>
 #include <linux/if_tun.h>
+#include <ctype.h>
 
 #include "connman.h"
 
@@ -1991,27 +1992,37 @@ static int inet_rtnl_recv(GIOChannel *chan, gpointer user_data)
        struct inet_rtnl_cb_data *rtnl_data = user_data;
        struct __connman_inet_rtnl_handle *rth = rtnl_data->rtnl;
        struct nlmsghdr *h = NULL;
+       struct sockaddr_nl nladdr;
+       socklen_t addr_len = sizeof(nladdr);
        unsigned char buf[4096];
        void *ptr = buf;
        gsize len;
-       int status;
+       int status, fd;
 
        memset(buf, 0, sizeof(buf));
+       memset(&nladdr, 0, sizeof(nladdr));
 
-       status = g_io_channel_read_chars(chan, (gchar *) buf,
-                                               sizeof(buf), &len, NULL);
+       fd = g_io_channel_unix_get_fd(chan);
 
-       DBG("status %d", status);
+       status = recvfrom(fd, buf, sizeof(buf), 0,
+                       (struct sockaddr *) &nladdr, &addr_len);
+       if (status < 0) {
+               if (errno == EINTR || errno == EAGAIN)
+                       return 0;
 
-       switch (status) {
-       case G_IO_STATUS_NORMAL:
-               break;
-       case G_IO_STATUS_AGAIN:
-               return 0;
-       default:
                return -1;
        }
 
+       if (status == 0)
+               return -1;
+
+       if (nladdr.nl_pid != 0) { /* not sent by kernel, ignore */
+               DBG("Received msg from %u, ignoring it", nladdr.nl_pid);
+               return 0;
+       }
+
+       len = status;
+
        while (len > 0) {
                struct nlmsgerr *err;
 
@@ -2151,7 +2162,7 @@ int __connman_inet_rtnl_addattr32(struct nlmsghdr *n, size_t maxlen, int type,
        struct rtattr *rta;
 
        if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen) {
-               DBG("Error! max allowed bound %d exceeded", maxlen);
+               DBG("Error! max allowed bound %zd exceeded", maxlen);
                return -1;
        }
        rta = NLMSG_TAIL(n);
@@ -2162,3 +2173,50 @@ int __connman_inet_rtnl_addattr32(struct nlmsghdr *n, size_t maxlen, int type,
 
        return 0;
 }
+
+/* Check routine modified from ics-dhcp 4.2.3-P2 */
+connman_bool_t connman_inet_check_hostname(const char *ptr, size_t len)
+{
+       const char *p;
+
+       /*
+        * Not empty or complete length not over 255 characters.
+        */
+       if ((len == 0) || (len > 256))
+               return FALSE;
+
+       /*
+        * Consists of [[:alnum:]-]+ labels separated by [.]
+        * a [_] is against RFC but seems to be "widely used"
+        */
+       for (p = ptr; (*p != 0) && (len-- > 0); p++) {
+
+               if ((*p == '-') || (*p == '_')) {
+                       /*
+                        * Not allowed at begin or end of a label.
+                        */
+                       if (((p - ptr) == 0) || (len == 0) || (p[1] == '.'))
+                               return FALSE;
+
+               } else if (*p == '.') {
+                       /*
+                        * Each label has to be 1-63 characters;
+                        * we allow [.] at the end ('foo.bar.')
+                        */
+                       size_t d = p - ptr;
+
+                       if ((d <= 0) || (d >= 64))
+                               return FALSE;
+
+                       ptr = p + 1; /* Jump to the next label */
+
+               } else if (isalnum((unsigned char)*p) == 0) {
+                       /*
+                        * Also numbers at the begin are fine
+                        */
+                       return FALSE;
+               }
+       }
+
+       return TRUE;
+}