Diff for /embedaddon/dnsmasq/src/edns0.c between versions 1.1.1.2 and 1.1.1.3

version 1.1.1.2, 2021/03/17 00:56:46 version 1.1.1.3, 2023/09/27 11:02:07
Line 1 Line 1
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
   
    This program is free software; you can redistribute it and/or modify     This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by     it under the terms of the GNU General Public License as published by
Line 178  size_t add_pseudoheader(struct dns_header *header, siz Line 178  size_t add_pseudoheader(struct dns_header *header, siz
             memcpy(buff, datap, rdlen);                     memcpy(buff, datap, rdlen);       
                       
           /* now, delete OPT RR */            /* now, delete OPT RR */
          plen = rrfilter(header, plen, 0);          plen = rrfilter(header, plen, RRFILTER_EDNS0);
                       
           /* Now, force addition of a new one */            /* Now, force addition of a new one */
           p = NULL;                   p = NULL;       
Line 264  static void encoder(unsigned char *in, char *out) Line 264  static void encoder(unsigned char *in, char *out)
   out[3] = char64(in[2]);    out[3] = char64(in[2]);
 }  }
   
   /* OPT_ADD_MAC = MAC is added (if available)
      OPT_ADD_MAC + OPT_STRIP_MAC = MAC is replaced, if not available, it is only removed
      OPT_STRIP_MAC = MAC is removed */
 static size_t add_dns_client(struct dns_header *header, size_t plen, unsigned char *limit,  static size_t add_dns_client(struct dns_header *header, size_t plen, unsigned char *limit,
                              union mysockaddr *l3, time_t now, int *cacheablep)                               union mysockaddr *l3, time_t now, int *cacheablep)
 {  {
  int maclen, replace = 2; /* can't get mac address, just delete any incoming. */  int replace = 0, maclen = 0;
   unsigned char mac[DHCP_CHADDR_MAX];    unsigned char mac[DHCP_CHADDR_MAX];
  char encode[18]; /* handle 6 byte MACs */  char encode[18]; /* handle 6 byte MACs ONLY */
   
  if ((maclen = find_mac(l3, mac, 1, now)) == 6)  if ((option_bool(OPT_MAC_B64) || option_bool(OPT_MAC_HEX)) && (maclen = find_mac(l3, mac, 1, now)) == 6)
     {      {
      replace = 1;      if (option_bool(OPT_STRIP_MAC))
      *cacheablep = 0;         replace = 1;
       *cacheablep = 0;
      if (option_bool(OPT_MAC_HEX))    
        print_mac(encode, mac, maclen);       if (option_bool(OPT_MAC_HEX))
      else         print_mac(encode, mac, maclen);
        {       else
          encoder(mac, encode);         {
          encoder(mac+3, encode+4);           encoder(mac, encode);
          encode[8] = 0;           encoder(mac+3, encode+4);
        }           encode[8] = 0;
          }
     }      }
     else if (option_bool(OPT_STRIP_MAC))
       replace = 2;
   
  return add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_NOMDEVICEID, (unsigned char *)encode, strlen(encode), 0, replace);   if (replace != 0 || maclen == 6)
     plen = add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_NOMDEVICEID, (unsigned char *)encode, strlen(encode), 0, replace);
 
   return plen;
 }  }
   
   
   /* OPT_ADD_MAC = MAC is added (if available)
      OPT_ADD_MAC + OPT_STRIP_MAC = MAC is replaced, if not available, it is only removed
      OPT_STRIP_MAC = MAC is removed */
 static size_t add_mac(struct dns_header *header, size_t plen, unsigned char *limit,  static size_t add_mac(struct dns_header *header, size_t plen, unsigned char *limit,
                       union mysockaddr *l3, time_t now, int *cacheablep)                        union mysockaddr *l3, time_t now, int *cacheablep)
 {  {
  int maclen;  int maclen = 0, replace = 0;
   unsigned char mac[DHCP_CHADDR_MAX];    unsigned char mac[DHCP_CHADDR_MAX];
    
  if ((maclen = find_mac(l3, mac, 1, now)) != 0)  if (option_bool(OPT_ADD_MAC) && (maclen = find_mac(l3, mac, 1, now)) != 0)
     {      {
       *cacheablep = 0;        *cacheablep = 0;
      plen = add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_MAC, mac, maclen, 0, 0);       if (option_bool(OPT_STRIP_MAC))
         replace = 1;
     }      }
     else if (option_bool(OPT_STRIP_MAC))
       replace = 2;
       
     if (replace != 0 || maclen != 0)
       plen = add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_MAC, mac, maclen, 0, replace);
   
   return plen;     return plen; 
 }  }
   
Line 378  static size_t calc_subnet_opt(struct subnet_opt *opt,  Line 396  static size_t calc_subnet_opt(struct subnet_opt *opt, 
   return len + 4;    return len + 4;
 }  }
     
static size_t add_source_addr(struct dns_header *header, size_t plen, unsigned char *limit, union mysockaddr *source, int *cacheable)/* OPT_CLIENT_SUBNET = client subnet is added
    OPT_CLIENT_SUBNET + OPT_STRIP_ECS = client subnet is replaced
    OPT_STRIP_ECS = client subnet is removed */
 static size_t add_source_addr(struct dns_header *header, size_t plen, unsigned char *limit,
                               union mysockaddr *source, int *cacheable)
 {  {
   /* http://tools.ietf.org/html/draft-vandergaast-edns-client-subnet-02 */    /* http://tools.ietf.org/html/draft-vandergaast-edns-client-subnet-02 */
       
  int len;  int replace = 0, len = 0;
   struct subnet_opt opt;    struct subnet_opt opt;
       
  len = calc_subnet_opt(&opt, source, cacheable);  if (option_bool(OPT_CLIENT_SUBNET))
  return add_pseudoheader(header, plen, (unsigned char *)limit, PACKETSZ, EDNS0_OPTION_CLIENT_SUBNET, (unsigned char *)&opt, len, 0, 0);    {
       if (option_bool(OPT_STRIP_ECS))
         replace = 1;
       len = calc_subnet_opt(&opt, source, cacheable);
     }
   else if (option_bool(OPT_STRIP_ECS))
     replace = 2;
   else
     return plen;
 
   return add_pseudoheader(header, plen, (unsigned char *)limit, PACKETSZ, EDNS0_OPTION_CLIENT_SUBNET, (unsigned char *)&opt, len, 0, replace);
 }  }
   
 int check_source(struct dns_header *header, size_t plen, unsigned char *pseudoheader, union mysockaddr *peer)  int check_source(struct dns_header *header, size_t plen, unsigned char *pseudoheader, union mysockaddr *peer)
Line 427  int check_source(struct dns_header *header, size_t ple Line 459  int check_source(struct dns_header *header, size_t ple
    return 1;     return 1;
 }  }
   
   /* See https://docs.umbrella.com/umbrella-api/docs/identifying-dns-traffic for
    * detailed information on packet formating.
    */
   #define UMBRELLA_VERSION    1
   #define UMBRELLA_TYPESZ     2
   
   #define UMBRELLA_ASSET      0x0004
   #define UMBRELLA_ASSETSZ    sizeof(daemon->umbrella_asset)
   #define UMBRELLA_ORG        0x0008
   #define UMBRELLA_ORGSZ      sizeof(daemon->umbrella_org)
   #define UMBRELLA_IPV4       0x0010
   #define UMBRELLA_IPV6       0x0020
   #define UMBRELLA_DEVICE     0x0040
   #define UMBRELLA_DEVICESZ   sizeof(daemon->umbrella_device)
   
   struct umbrella_opt {
     u8 magic[4];
     u8 version;
     u8 flags;
     /* We have 4 possible fields since we'll never send both IPv4 and
      * IPv6, so using the larger of the two to calculate max buffer size.
      * Each field also has a type header.  So the following accounts for
      * the type headers and each field size to get a max buffer size.
      */
     u8 fields[4 * UMBRELLA_TYPESZ + UMBRELLA_ORGSZ + IN6ADDRSZ + UMBRELLA_DEVICESZ + UMBRELLA_ASSETSZ];
   };
   
   static size_t add_umbrella_opt(struct dns_header *header, size_t plen, unsigned char *limit, union mysockaddr *source, int *cacheable)
   {
     *cacheable = 0;
   
     struct umbrella_opt opt = {{"ODNS"}, UMBRELLA_VERSION, 0, {}};
     u8 *u = &opt.fields[0];
     int family = source->sa.sa_family;
     int size = family == AF_INET ? INADDRSZ : IN6ADDRSZ;
   
     if (daemon->umbrella_org)
       {
         PUTSHORT(UMBRELLA_ORG, u);
         PUTLONG(daemon->umbrella_org, u);
       }
     
     PUTSHORT(family == AF_INET ? UMBRELLA_IPV4 : UMBRELLA_IPV6, u);
     memcpy(u, get_addrp(source, family), size);
     u += size;
     
     if (option_bool(OPT_UMBRELLA_DEVID))
       {
         PUTSHORT(UMBRELLA_DEVICE, u);
         memcpy(u, (char *)&daemon->umbrella_device, UMBRELLA_DEVICESZ);
         u += UMBRELLA_DEVICESZ;
       }
   
     if (daemon->umbrella_asset)
       {
         PUTSHORT(UMBRELLA_ASSET, u);
         PUTLONG(daemon->umbrella_asset, u);
       }
     
     return add_pseudoheader(header, plen, (unsigned char *)limit, PACKETSZ, EDNS0_OPTION_UMBRELLA, (unsigned char *)&opt, u - (u8 *)&opt, 0, 1);
   }
   
 /* Set *check_subnet if we add a client subnet option, which needs to checked   /* Set *check_subnet if we add a client subnet option, which needs to checked 
    in the reply. Set *cacheable to zero if we add an option which the answer     in the reply. Set *cacheable to zero if we add an option which the answer
    may depend on. */     may depend on. */
 size_t add_edns0_config(struct dns_header *header, size_t plen, unsigned char *limit,   size_t add_edns0_config(struct dns_header *header, size_t plen, unsigned char *limit, 
                        union mysockaddr *source, time_t now, int *check_subnet, int *cacheable)                            union mysockaddr *source, time_t now, int *cacheable)    
 {  {
   *check_subnet = 0;  
   *cacheable = 1;    *cacheable = 1;
       
  if (option_bool(OPT_ADD_MAC))  plen  = add_mac(header, plen, limit, source, now, cacheable);
    plen  = add_mac(header, plen, limit, source, now, cacheable);  plen = add_dns_client(header, plen, limit, source, now, cacheable);
       
   if (option_bool(OPT_MAC_B64) || option_bool(OPT_MAC_HEX))  
     plen = add_dns_client(header, plen, limit, source, now, cacheable);  
     
   if (daemon->dns_client_id)    if (daemon->dns_client_id)
     plen = add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_NOMCPEID,       plen = add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_NOMCPEID, 
                             (unsigned char *)daemon->dns_client_id, strlen(daemon->dns_client_id), 0, 1);                              (unsigned char *)daemon->dns_client_id, strlen(daemon->dns_client_id), 0, 1);
   
     if (option_bool(OPT_UMBRELLA))
       plen = add_umbrella_opt(header, plen, limit, source, cacheable);
       
  if (option_bool(OPT_CLIENT_SUBNET))  plen = add_source_addr(header, plen, limit, source, cacheable);
    {          
      plen = add_source_addr(header, plen, limit, source, cacheable);  
      *check_subnet = 1; 
    } 
           
   return plen;    return plen;
 }  }

Removed from v.1.1.1.2  
changed lines
  Added in v.1.1.1.3


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>