~ubuntu-branches/ubuntu/utopic/dnsmasq/utopic

« back to all changes in this revision

Viewing changes to src/forward.c

  • Committer: Package Import Robot
  • Author(s): Simon Kelley
  • Date: 2013-08-04 14:53:22 UTC
  • mfrom: (0.5.6) (12.2.14 sid)
  • Revision ID: package-import@ubuntu.com-20130804145322-m7jo0uo06te27pxh
Tags: 2.67-1
 * New upstream.
 * Update resolvconf script. (closes: #720732)

Show diffs side-by-side

added added

removed removed

Lines of Context:
284
284
          forward->fd = udpfd;
285
285
          forward->crc = crc;
286
286
          forward->forwardall = 0;
 
287
          forward->flags = 0;
287
288
          if (norebind)
288
289
            forward->flags |= FREC_NOREBIND;
289
290
          if (header->hb4 & HB4_CD)
328
329
      struct server *firstsentto = start;
329
330
      int forwarded = 0;
330
331
      
331
 
      if (udpaddr && option_bool(OPT_ADD_MAC))
332
 
        plen = add_mac(header, plen, ((char *) header) + PACKETSZ, udpaddr);
 
332
      if (option_bool(OPT_ADD_MAC))
 
333
        plen = add_mac(header, plen, ((char *) header) + PACKETSZ, &forward->source);
333
334
      
 
335
      if (option_bool(OPT_CLIENT_SUBNET))
 
336
        {
 
337
          size_t new = add_source_addr(header, plen, ((char *) header) + PACKETSZ, &forward->source); 
 
338
          if (new != plen)
 
339
            {
 
340
              plen = new;
 
341
              forward->flags |= FREC_HAS_SUBNET;
 
342
            }
 
343
        }
 
344
 
334
345
      while (1)
335
346
        { 
336
347
          /* only send to servers dealing with our domain.
372
383
                  if (option_bool(OPT_CONNTRACK))
373
384
                    {
374
385
                      unsigned int mark;
375
 
                      if (get_incoming_mark(udpaddr, dst_addr, 0, &mark))
 
386
                      if (get_incoming_mark(&forward->source, &forward->dest, 0, &mark))
376
387
                        setsockopt(fd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
377
388
                    }
378
389
#endif
435
446
  return 0;
436
447
}
437
448
 
438
 
static size_t process_reply(struct dns_header *header, time_t now, 
439
 
                            struct server *server, size_t n, int check_rebind, int checking_disabled)
 
449
static size_t process_reply(struct dns_header *header, time_t now, struct server *server, size_t n, int check_rebind, 
 
450
                            int checking_disabled, int check_subnet, union mysockaddr *query_source)
440
451
{
441
452
  unsigned char *pheader, *sizep;
442
453
  char **sets = 0;
465
476
     than we allow, trim it so that we don't get overlarge
466
477
     requests for the client. We can't do this for signed packets. */
467
478
 
468
 
  if ((pheader = find_pseudoheader(header, n, &plen, &sizep, &is_sign)) && !is_sign)
 
479
  if ((pheader = find_pseudoheader(header, n, &plen, &sizep, &is_sign)))
469
480
    {
470
 
      unsigned short udpsz;
471
 
      unsigned char *psave = sizep;
 
481
      if (!is_sign)
 
482
        {
 
483
          unsigned short udpsz;
 
484
          unsigned char *psave = sizep;
 
485
          
 
486
          GETSHORT(udpsz, sizep);
 
487
          if (udpsz > daemon->edns_pktsz)
 
488
            PUTSHORT(daemon->edns_pktsz, psave);
 
489
        }
472
490
      
473
 
      GETSHORT(udpsz, sizep);
474
 
      if (udpsz > daemon->edns_pktsz)
475
 
        PUTSHORT(daemon->edns_pktsz, psave);
 
491
      if (check_subnet && !check_source(header, plen, pheader, query_source))
 
492
        {
 
493
          my_syslog(LOG_WARNING, _("discarding DNS reply: subnet option mismatch"));
 
494
          return 0;
 
495
        }
476
496
    }
 
497
      
477
498
 
478
499
  /* RFC 4035 sect 4.6 para 3 */
479
500
  if (!is_sign && !option_bool(OPT_DNSSEC))
480
 
     header->hb4 &= ~HB4_AD;
 
501
    header->hb4 &= ~HB4_AD;
481
502
 
482
503
  if (OPCODE(header) != QUERY || (RCODE(header) != NOERROR && RCODE(header) != NXDOMAIN))
483
504
    return n;
632
653
      if (!option_bool(OPT_NO_REBIND))
633
654
        check_rebind = 0;
634
655
      
635
 
      if ((nn = process_reply(header, now, server, (size_t)n, check_rebind, forward->flags & FREC_CHECKING_DISABLED)))
 
656
      if ((nn = process_reply(header, now, server, (size_t)n, check_rebind, forward->flags & FREC_CHECKING_DISABLED,
 
657
                              forward->flags & FREC_HAS_SUBNET, &forward->source)))
636
658
        {
637
659
          header->id = htons(forward->orig_id);
638
660
          header->hb4 |= HB4_RA; /* recursion if available */
654
676
  size_t m;
655
677
  ssize_t n;
656
678
  int if_index = 0;
657
 
  int auth_dns = 0;
 
679
  int local_auth = 0, auth_dns = 0;
658
680
  struct iovec iov[1];
659
681
  struct msghdr msg;
660
682
  struct cmsghdr *cmptr;
788
810
      if (!iface_check(listen->family, &dst_addr, ifr.ifr_name, &auth_dns))
789
811
        {
790
812
           if (!option_bool(OPT_CLEVERBIND))
791
 
             enumerate_interfaces(); 
792
 
           if (!loopback_exception(listen->fd, listen->family, &dst_addr, ifr.ifr_name))
 
813
             enumerate_interfaces(0); 
 
814
           if (!loopback_exception(listen->fd, listen->family, &dst_addr, ifr.ifr_name) &&
 
815
               !label_exception(if_index, listen->family, &dst_addr))
793
816
             return;
794
817
        }
795
818
 
807
830
          
808
831
          /* interface may be new */
809
832
          if (!iface && !option_bool(OPT_CLEVERBIND))
810
 
            enumerate_interfaces(); 
 
833
            enumerate_interfaces(0); 
811
834
          
812
835
          for (iface = daemon->interfaces; iface; iface = iface->next)
813
836
            if (iface->addr.sa.sa_family == AF_INET &&
825
848
  if (extract_request(header, (size_t)n, daemon->namebuff, &type))
826
849
    {
827
850
      char types[20];
 
851
#ifdef HAVE_AUTH
 
852
      struct auth_zone *zone;
 
853
#endif
828
854
 
829
855
      querystr(auth_dns ? "auth" : "query", types, type);
830
856
 
836
862
        log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff, 
837
863
                  (struct all_addr *)&source_addr.in6.sin6_addr, types);
838
864
#endif
 
865
 
 
866
#ifdef HAVE_AUTH
 
867
      /* find queries for zones we're authoritative for, and answer them directly */
 
868
      if (!auth_dns)
 
869
        for (zone = daemon->auth_zones; zone; zone = zone->next)
 
870
          if (in_zone(zone, daemon->namebuff, NULL))
 
871
            {
 
872
              auth_dns = 1;
 
873
              local_auth = 1;
 
874
              break;
 
875
            }
 
876
#endif
839
877
    }
840
 
 
 
878
  
841
879
#ifdef HAVE_AUTH
842
880
  if (auth_dns)
843
881
    {
844
 
      m = answer_auth(header, ((char *) header) + PACKETSZ, (size_t)n, now, &source_addr);
 
882
      m = answer_auth(header, ((char *) header) + PACKETSZ, (size_t)n, now, &source_addr, local_auth);
845
883
      if (m >= 1)
846
 
        send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND),
847
 
                  (char *)header, m, &source_addr, &dst_addr, if_index);
 
884
        {
 
885
          send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND),
 
886
                    (char *)header, m, &source_addr, &dst_addr, if_index);
 
887
          daemon->auth_answer++;
 
888
        }
848
889
    }
849
890
  else
850
891
#endif
875
916
{
876
917
  size_t size = 0;
877
918
  int norebind = 0;
878
 
  int checking_disabled;
 
919
  int local_auth = 0;
 
920
  int checking_disabled, check_subnet;
879
921
  size_t m;
880
922
  unsigned short qtype;
881
923
  unsigned int gotname;
882
924
  unsigned char c1, c2;
883
 
  /* Max TCP packet + slop */
884
 
  unsigned char *packet = whine_malloc(65536 + MAXDNAME + RRFIXEDSZ);
885
 
  struct dns_header *header;
 
925
  /* Max TCP packet + slop + size */
 
926
  unsigned char *packet = whine_malloc(65536 + MAXDNAME + RRFIXEDSZ + sizeof(u16));
 
927
  unsigned char *payload = &packet[2];
 
928
  /* largest field in header is 16-bits, so this is still sufficiently aligned */
 
929
  struct dns_header *header = (struct dns_header *)payload;
 
930
  u16 *length = (u16 *)packet;
886
931
  struct server *last_server;
887
932
  struct in_addr dst_addr_4;
888
933
  union mysockaddr peer_addr;
896
941
      if (!packet ||
897
942
          !read_write(confd, &c1, 1, 1) || !read_write(confd, &c2, 1, 1) ||
898
943
          !(size = c1 << 8 | c2) ||
899
 
          !read_write(confd, packet, size, 1))
 
944
          !read_write(confd, payload, size, 1))
900
945
        return packet; 
901
946
  
902
947
      if (size < (int)sizeof(struct dns_header))
903
948
        continue;
904
949
      
905
 
      header = (struct dns_header *)packet;
 
950
      check_subnet = 0;
906
951
 
907
952
      /* save state of "cd" flag in query */
908
953
      checking_disabled = header->hb4 & HB4_CD;
913
958
      if ((gotname = extract_request(header, (unsigned int)size, daemon->namebuff, &qtype)))
914
959
        {
915
960
          char types[20];
916
 
          
 
961
#ifdef HAVE_AUTH
 
962
          struct auth_zone *zone;
 
963
#endif
917
964
          querystr(auth_dns ? "auth" : "query", types, qtype);
918
965
          
919
966
          if (peer_addr.sa.sa_family == AF_INET) 
924
971
            log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff, 
925
972
                      (struct all_addr *)&peer_addr.in6.sin6_addr, types);
926
973
#endif
 
974
          
 
975
#ifdef HAVE_AUTH
 
976
          /* find queries for zones we're authoritative for, and answer them directly */
 
977
          if (!auth_dns)
 
978
            for (zone = daemon->auth_zones; zone; zone = zone->next)
 
979
              if (in_zone(zone, daemon->namebuff, NULL))
 
980
                {
 
981
                  auth_dns = 1;
 
982
                  local_auth = 1;
 
983
                  break;
 
984
                }
 
985
#endif
927
986
        }
928
987
      
929
988
      if (local_addr->sa.sa_family == AF_INET)
933
992
      
934
993
#ifdef HAVE_AUTH
935
994
      if (auth_dns)
936
 
        m = answer_auth(header, ((char *) header) + 65536, (size_t)size, now, &peer_addr);
 
995
        m = answer_auth(header, ((char *) header) + 65536, (size_t)size, now, &peer_addr, local_auth);
937
996
      else
938
997
#endif
939
998
        {
953
1012
              
954
1013
              if (option_bool(OPT_ADD_MAC))
955
1014
                size = add_mac(header, size, ((char *) header) + 65536, &peer_addr);
956
 
              
 
1015
                
 
1016
              if (option_bool(OPT_CLIENT_SUBNET))
 
1017
                {
 
1018
                  size_t new = add_source_addr(header, size, ((char *) header) + 65536, &peer_addr);
 
1019
                  if (size != new)
 
1020
                    {
 
1021
                      size = new;
 
1022
                      check_subnet = 1;
 
1023
                    }
 
1024
                }
 
1025
 
957
1026
              if (gotname)
958
1027
                flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain, &norebind);
959
1028
              
1020
1089
#endif  
1021
1090
                        }
1022
1091
                      
1023
 
                      c1 = size >> 8;
1024
 
                      c2 = size;
 
1092
                      *length = htons(size);
1025
1093
                      
1026
 
                      if (!read_write(last_server->tcpfd, &c1, 1, 0) ||
1027
 
                          !read_write(last_server->tcpfd, &c2, 1, 0) ||
1028
 
                          !read_write(last_server->tcpfd, packet, size, 0) ||
 
1094
                      if (!read_write(last_server->tcpfd, packet, size + sizeof(u16), 0) ||
1029
1095
                          !read_write(last_server->tcpfd, &c1, 1, 1) ||
1030
1096
                          !read_write(last_server->tcpfd, &c2, 1, 1))
1031
1097
                        {
1035
1101
                        } 
1036
1102
                      
1037
1103
                      m = (c1 << 8) | c2;
1038
 
                      if (!read_write(last_server->tcpfd, packet, m, 1))
 
1104
                      if (!read_write(last_server->tcpfd, payload, m, 1))
1039
1105
                        return packet;
1040
1106
                      
1041
1107
                      if (!gotname)
1057
1123
                         sending replies containing questions and bogus answers. */
1058
1124
                      if (crc == questions_crc(header, (unsigned int)m, daemon->namebuff))
1059
1125
                        m = process_reply(header, now, last_server, (unsigned int)m, 
1060
 
                                          option_bool(OPT_NO_REBIND) && !norebind, checking_disabled);
 
1126
                                          option_bool(OPT_NO_REBIND) && !norebind, checking_disabled,
 
1127
                                          check_subnet, &peer_addr);
1061
1128
                      
1062
1129
                      break;
1063
1130
                    }
1071
1138
          
1072
1139
      check_log_writer(NULL);
1073
1140
      
1074
 
      c1 = m>>8;
1075
 
      c2 = m;
1076
 
      if (m == 0 ||
1077
 
          !read_write(confd, &c1, 1, 0) ||
1078
 
          !read_write(confd, &c2, 1, 0) || 
1079
 
          !read_write(confd, packet, m, 0))
 
1141
      *length = htons(m);
 
1142
           
 
1143
      if (m == 0 || !read_write(confd, packet, m + sizeof(u16), 0))
1080
1144
        return packet;
1081
1145
    }
1082
1146
}
1209
1273
  /* none available, calculate time 'till oldest record expires */
1210
1274
  if (count > daemon->ftabsize)
1211
1275
    {
 
1276
      static time_t last_log = 0;
 
1277
      
1212
1278
      if (oldest && wait)
1213
1279
        *wait = oldest->time + (time_t)TIMEOUT - now;
 
1280
      
 
1281
      if ((int)difftime(now, last_log) > 5)
 
1282
        {
 
1283
          last_log = now;
 
1284
          my_syslog(LOG_WARNING, _("Maximum number of concurrent DNS queries reached (max: %d)"), daemon->ftabsize);
 
1285
        }
 
1286
 
1214
1287
      return NULL;
1215
1288
    }
1216
1289