Home | History | Annotate | Download | only in avahi-core
      1 /***
      2   This file is part of avahi.
      3 
      4   avahi is free software; you can redistribute it and/or modify it
      5   under the terms of the GNU Lesser General Public License as
      6   published by the Free Software Foundation; either version 2.1 of the
      7   License, or (at your option) any later version.
      8 
      9   avahi is distributed in the hope that it will be useful, but WITHOUT
     10   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     11   or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
     12   Public License for more details.
     13 
     14   You should have received a copy of the GNU Lesser General Public
     15   License along with avahi; if not, write to the Free Software
     16   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
     17   USA.
     18 ***/
     19 
     20 #ifdef HAVE_CONFIG_H
     21 #include <config.h>
     22 #endif
     23 
     24 #include <sys/types.h>
     25 #include <netinet/in.h>
     26 #include <sys/socket.h>
     27 #include <arpa/inet.h>
     28 #include <string.h>
     29 #include <assert.h>
     30 
     31 #include "addr-util.h"
     32 
     33 AvahiAddress *avahi_address_from_sockaddr(const struct sockaddr* sa, AvahiAddress *ret_addr) {
     34     assert(sa);
     35     assert(ret_addr);
     36 
     37     assert(sa->sa_family == AF_INET || sa->sa_family == AF_INET6);
     38 
     39     ret_addr->proto = avahi_af_to_proto(sa->sa_family);
     40 
     41     if (sa->sa_family == AF_INET)
     42         memcpy(&ret_addr->data.ipv4, &((const struct sockaddr_in*) sa)->sin_addr, sizeof(ret_addr->data.ipv4));
     43     else
     44         memcpy(&ret_addr->data.ipv6, &((const struct sockaddr_in6*) sa)->sin6_addr, sizeof(ret_addr->data.ipv6));
     45 
     46     return ret_addr;
     47 }
     48 
     49 uint16_t avahi_port_from_sockaddr(const struct sockaddr* sa) {
     50     assert(sa);
     51 
     52     assert(sa->sa_family == AF_INET || sa->sa_family == AF_INET6);
     53 
     54     if (sa->sa_family == AF_INET)
     55         return ntohs(((const struct sockaddr_in*) sa)->sin_port);
     56     else
     57         return ntohs(((const struct sockaddr_in6*) sa)->sin6_port);
     58 }
     59 
     60 int avahi_address_is_ipv4_in_ipv6(const AvahiAddress *a) {
     61 
     62     static const uint8_t ipv4_in_ipv6[] = {
     63         0x00, 0x00, 0x00, 0x00,
     64         0x00, 0x00, 0x00, 0x00,
     65         0xFF, 0xFF, 0xFF, 0xFF
     66     };
     67 
     68     assert(a);
     69 
     70     if (a->proto != AVAHI_PROTO_INET6)
     71         return 0;
     72 
     73     return memcmp(a->data.ipv6.address, ipv4_in_ipv6, sizeof(ipv4_in_ipv6)) == 0;
     74 }
     75 
     76 #define IPV4LL_NETWORK 0xA9FE0000L
     77 #define IPV4LL_NETMASK 0xFFFF0000L
     78 #define IPV6LL_NETWORK 0xFE80
     79 #define IPV6LL_NETMASK 0xFFC0
     80 
     81 int avahi_address_is_link_local(const AvahiAddress *a) {
     82     assert(a);
     83 
     84     if (a->proto == AVAHI_PROTO_INET) {
     85         uint32_t n = ntohl(a->data.ipv4.address);
     86         return (n & IPV4LL_NETMASK) == IPV4LL_NETWORK;
     87     }
     88     else if (a->proto == AVAHI_PROTO_INET6) {
     89         unsigned n = (a->data.ipv6.address[0] << 8) | (a->data.ipv6.address[1] << 0);
     90         return (n & IPV6LL_NETMASK) == IPV6LL_NETWORK;
     91     }
     92 
     93     return 0;
     94 }
     95