#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)getnetbyaddr.c 8.1 (Berkeley) 6/4/93";
static char sccsid_[] = "from getnetnamadr.c 1.4 (Coimbra) 93/06/03";
-static char rcsid[] = "$Id: getnetnamadr.c,v 1.3 2002/06/12 17:40:29 epeyton Exp $";
+static char rcsid[] = "$Id: getnetnamadr.c,v 1.3.44.1 2002/11/19 01:20:51 bbraun Exp $";
#endif /* LIBC_SCCS and not lint */
#include <sys/param.h>
register int n;
u_char *eom;
int type, class, buflen, ancount, qdcount, haveanswer, i, nchar;
- char aux1[30], aux2[30], ans[30], *in, *st, *pauxt, *bp, **ap,
+ char aux1[30], aux2[30], *in, *st, *pauxt, *bp, **ap,
*paux1 = &aux1[0], *paux2 = &aux2[0], flag = 0;
-static struct netent net_entry;
-static char *net_aliases[MAXALIASES], *netbuf = NULL;
+ static struct netent net_entry;
+ static char *net_aliases[MAXALIASES], *netbuf = NULL;
+ static char ans[MAXDNAME];
if (netbuf == NULL) {
netbuf = malloc(BUFSIZ+1);
h_errno = TRY_AGAIN;
return (NULL);
}
- while (qdcount-- > 0)
- cp += __dn_skipname(cp, eom) + QFIXEDSZ;
+ while (qdcount-- > 0) {
+ n = __dn_skipname(cp, eom);
+ if (n < 0 || (cp + n + QFIXEDSZ) > eom) {
+ h_errno = NO_RECOVERY;
+ return(NULL);
+ }
+ cp += n + QFIXEDSZ;
+ }
ap = net_aliases;
*ap = NULL;
net_entry.n_aliases = net_aliases;
break;
cp += n;
ans[0] = '\0';
- (void)strcpy(&ans[0], bp);
+ (void)strcpy(ans, bp);
GETSHORT(type, cp);
GETSHORT(class, cp);
cp += INT32SZ; /* TTL */
return (NULL);
}
cp += n;
- *ap++ = bp;
- bp += strlen(bp) + 1;
- net_entry.n_addrtype =
- (class == C_IN) ? AF_INET : AF_UNSPEC;
- haveanswer++;
+ if ((ap + 2) < &net_aliases[MAXALIASES]) {
+ *ap++ = bp;
+ bp += strlen(bp) + 1;
+ net_entry.n_addrtype =
+ (class == C_IN) ? AF_INET : AF_UNSPEC;
+ haveanswer++;
+ }
}
}
if (haveanswer) {
net_entry.n_net = 0L;
break;
case BYNAME:
- in = *net_entry.n_aliases;
- net_entry.n_name = &ans[0];
+ ap = net_entry.n_aliases;
+ next_alias:
+ in = *ap++;
+ if (in == NULL) {
+ h_errno = HOST_NOT_FOUND;
+ return (NULL);
+ }
+ net_entry.n_name = ans;
aux2[0] = '\0';
for (i = 0; i < 4; i++) {
for (st = in, nchar = 0;
- *st != '.';
+ isdigit((unsigned char)*st);
st++, nchar++)
;
- if (nchar != 1 || *in != '0' || flag) {
- flag = 1;
- (void)strncpy(paux1,
- (i==0) ? in : in-1,
- (i==0) ?nchar : nchar+1);
- paux1[(i==0) ? nchar : nchar+1] = '\0';
- pauxt = paux2;
- paux2 = strcat(paux1, paux2);
- paux1 = pauxt;
- }
+
+ if (*st != '.' || nchar == 0 || nchar > 3)
+ goto next_alias;
+ if (i != 0)
+ nchar++;
+ (void)strncpy(paux1, in, nchar);
+ paux1[nchar] = '\0';
+ pauxt = paux2;
+ paux2 = strcat(paux1, paux2);
+ paux1 = pauxt;
in = ++st;
}
+
+ if (strcasecmp(in, "IN-ADDR.ARPA") != 0)
+ goto next_alias;
net_entry.n_net = inet_network(paux2);
break;
}
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93";
-static char rcsid[] = "$Id: res_send.c,v 1.2 1999/10/14 21:56:45 wsanchez Exp $";
+static char rcsid[] = "$Id: res_send.c,v 1.2.202.1 2002/11/06 17:30:17 majka Exp $";
#endif /* LIBC_SCCS and not lint */
/* change this to "0"
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <arpa/inet.h>
+#include <ifaddrs.h>
+#include <net/if.h>
#include <stdio.h>
#include <netdb.h>
}
#endif
+extern struct __res_state _res_shadow;
+
static res_send_qhook Qhook = NULL;
static res_send_rhook Rhook = NULL;
return (1);
}
+static int res_using_defaults()
+{
+ int i;
+
+ if (_res.nscount != _res_shadow.nscount)
+ return 0;
+
+ for (i = 0; i < _res.nscount; i++) {
+ /* Check that the address and port have not changed */
+ if ((_res.nsaddr_list[i].sin_addr.s_addr !=
+ _res_shadow.nsaddr_list[i].sin_addr.s_addr) ||
+ (_res.nsaddr_list[i].sin_port !=
+ _res_shadow.nsaddr_list[i].sin_port)) {
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+/* Returns whether a dns encoded name should be sent to multicast or not */
+static int dns_is_local_name(const u_int8_t *name)
+{
+ const u_int8_t *d0 = NULL; // Top-Level Domain
+ const u_int8_t *d1 = NULL; // Second-Level Domain
+ const u_int8_t *d2 = NULL; // etc.
+ const u_int8_t *d3 = NULL;
+
+ while (*name)
+ {
+ d3 = d2;
+ d2 = d1;
+ d1 = d0;
+ d0 = name;
+ name += 1 + *name;
+ }
+
+ // "local" domains need to be resolved with multicast
+ // "local."
+ if (d0[0] == 5 && strncasecmp((char *)d0+1, "local", 5) == 0) return 1;
+
+ // "local.arpa."
+ if (d1 && d1[0] == 5 && strncasecmp((char *)d1+1, "local", 5) == 0 &&
+ d0[0] == 4 && strncasecmp((char *)d0+1, "arpa", 4) == 0) return 1;
+
+ // "local.int."
+ if (d1 && d1[0] == 5 && strncasecmp((char *)d1+1, "local", 5) == 0 &&
+ d0[0] == 3 && strncasecmp((char *)d0+1, "int", 3) == 0) return 1;
+
+ // The network 169.254/16 is defined to be link-local,
+ // so lookups in 254.169.in-addr.arpa. also need to be resolved with local multicast
+ if (d3 && d3[0] == 3 && strncasecmp((char *)d3+1, "254", 3) == 0 &&
+ d2 && d2[0] == 3 && strncasecmp((char *)d2+1, "169", 3) == 0 &&
+ d1 && d1[0] == 7 && strncasecmp((char *)d1+1, "in-addr", 7) == 0 &&
+ d0[0] == 4 && strncasecmp((char *)d0+1, "arpa", 4) == 0) return 1;
+
+ return 0;
+}
+
+#define DNS_LOCAL_DOMAIN_SERVICE_PORT 5353
+#define DNS_HEADER_SIZE 12
+
+#if BYTE_ORDER == BIG_ENDIAN
+#define my_htons(x) (x)
+#define my_htonl(x) (x)
+#else
+#define my_htons(x) ((((u_int16_t)x) >> 8) | (((u_int16_t)x) << 8))
+#define my_htonl(x) (((x) >> 24) | (((x) & 0x00FF0000) >> 16) | \
+ (((x) & 0x0000FF00) << 16) | ((x) << 24))
+#endif
+
+static const struct sockaddr_in mDNS_addr =
+{
+ sizeof(mDNS_addr),
+ AF_INET,
+ my_htons(DNS_LOCAL_DOMAIN_SERVICE_PORT),
+ {my_htonl(0xE00000FB)} /* 224.0.0.251 */
+};
+
int
res_send(buf, buflen, ans, anssiz)
const u_char *buf;
HEADER *anhp = (HEADER *) ans;
int gotsomewhere, connreset, terrno, try, v_circuit, resplen, ns;
register int n;
- u_int badns; /* XXX NSMAX can't exceed #/bits in this var */
+ u_int badns; /* XXX NSMAX can't exceed #/bits in this var */
+ int multicast;
if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
/* errno should have been set by res_init() in this case. */
terrno = ETIMEDOUT;
badns = 0;
+ if (res_using_defaults() &&
+ dns_is_local_name((u_int8_t*)(buf + DNS_HEADER_SIZE))) {
+ multicast = 1;
+ v_circuit = 0;
+ } else {
+ multicast = 0;
+ }
+
+
/*
* Send request, RETRY times, or until successful
*/
for (try = 0; try < _res.retry; try++) {
- for (ns = 0; ns < _res.nscount; ns++) {
- struct sockaddr_in *nsap = &_res.nsaddr_list[ns];
+ for (ns = 0; (multicast == 0 && ns < _res.nscount) ||
+ (multicast == 1 && ns < 1) ; ns++) {
+ struct sockaddr_in *nsap;
+ if (multicast == 0)
+ nsap = &_res.nsaddr_list[ns];
+ else
+ nsap = (struct sockaddr_in*)&mDNS_addr; /* const cast */
same_ns:
if (badns & (1 << ns)) {
_res_close();
* as we wish to receive answers from the first
* server to respond.
*/
- if (_res.nscount == 1 || (try == 0 && ns == 0)) {
+ if ((_res.nscount == 1 || (try == 0 && ns == 0)) && multicast == 0) {
/*
* Connect only if we are sure we won't
* receive a response from another server.
connected = 0;
errno = 0;
}
- if (sendto(s, (char*)buf, buflen, 0,
- (struct sockaddr *)nsap,
- sizeof(struct sockaddr))
- != buflen) {
- Aerror(stderr, "sendto", errno, *nsap);
- badns |= (1 << ns);
- _res_close();
- goto next_ns;
+
+ if (multicast) {
+ struct ifaddrs* addrs;
+ struct ifaddrs* curAddr;
+ const int twofivefive = 255;
+
+ // multicast packets with TTL 255
+ if(setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, &twofivefive, sizeof(twofivefive))) {
+ Perror(stderr, "setsocketopt - IP_MULTICAST_TTL", errno);
+ _res_close();
+ return (0);
+ }
+
+ if (getifaddrs(&addrs) != 0)
+ {
+ Perror(stderr, "getifaddrs", errno);
+ _res_close();
+ return (0);
+ }
+
+ /* multicast should send request on all multicast capable interfaces */
+ for (curAddr = addrs; curAddr != NULL; curAddr = curAddr->ifa_next) {
+ if ((curAddr->ifa_addr->sa_family) == AF_INET &&
+ (curAddr->ifa_flags & IFF_MULTICAST) != 0 &&
+ (curAddr->ifa_flags & IFF_POINTOPOINT) == 0) {
+ struct in_addr* if_ip_addr = &((struct sockaddr_in*)curAddr->ifa_addr)->sin_addr;
+
+ if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF,
+ if_ip_addr, sizeof(*if_ip_addr)) != 0) {
+ freeifaddrs(addrs);
+ Perror(stderr, "setsocketopt - IP_MULTICAST_IF", errno);
+ _res_close();
+ return (0);
+ }
+
+ if (sendto(s, (char*)buf, buflen, 0,
+ (struct sockaddr *)nsap, sizeof *nsap) != buflen)
+ {
+ freeifaddrs(addrs);
+ Aerror(stderr, "sendto", errno, *nsap);
+ _res_close();
+ return (0);
+ }
+ }
+ }
+
+ freeifaddrs(addrs);
+ } else {
+ if (sendto(s, (char*)buf, buflen, 0,
+ (struct sockaddr *)nsap,
+ sizeof(struct sockaddr))
+ != buflen) {
+ Aerror(stderr, "sendto", errno, *nsap);
+ badns |= (1 << ns);
+ _res_close();
+ goto next_ns;
+ }
}
}
timeout.tv_sec = (_res.retrans << try);
if (try > 0)
timeout.tv_sec /= _res.nscount;
- if ((long) timeout.tv_sec <= 0)
+ if ((long) timeout.tv_sec <= 0 || multicast)
timeout.tv_sec = 1;
timeout.tv_usec = 0;
wait:
}
#if CHECK_SRVR_ADDR
if (!(_res.options & RES_INSECURE1) &&
- !res_isourserver(&from)) {
+ multicast == 0 && !res_isourserver(&from)) {
/*
* response from wrong server? ignore it.
* XXX - potential security hazard could