1 /* $NetBSD: loc.c,v 1.5 2014/12/10 04:37:56 christos Exp $ */
5 /* Id: loc.c,v 1.1 2008/02/15 01:47:15 marka Exp */
12 Prints the actual usage
17 (void) fprintf (stderr
,
18 "Usage: %s: [-v] [-d nnn] hostname\n", progname
);
29 (void) fprintf (stderr
,
30 "%s: %s\n", progname
, message
);
35 ** IN_ADDR_ARPA -- Convert dotted quad string to reverse in-addr.arpa
36 ** ------------------------------------------------------------------
39 ** Pointer to appropriate reverse in-addr.arpa name
40 ** with trailing dot to force absolute domain name.
41 ** NULL in case of invalid dotted quad input string.
45 #define ARPA_ROOT "in-addr.arpa"
49 in_addr_arpa (dottedquad
)
50 char *dottedquad
; /* input string with dotted quad */
52 static char addrbuf
[4 * 4 + sizeof (ARPA_ROOT
) + 2];
56 n
= sscanf (dottedquad
, "%u.%u.%u.%u", &a
[0], &a
[1], &a
[2], &a
[3]);
60 (void) sprintf (addrbuf
, "%u.%u.%u.%u.%s.",
61 a
[3] & 0xff, a
[2] & 0xff, a
[1] & 0xff, a
[0] & 0xff, ARPA_ROOT
);
65 (void) sprintf (addrbuf
, "%u.%u.%u.%s.",
66 a
[2] & 0xff, a
[1] & 0xff, a
[0] & 0xff, ARPA_ROOT
);
70 (void) sprintf (addrbuf
, "%u.%u.%s.",
71 a
[1] & 0xff, a
[0] & 0xff, ARPA_ROOT
);
75 (void) sprintf (addrbuf
, "%u.%s.",
76 a
[0] & 0xff, ARPA_ROOT
);
91 Returns a human-readable version of the LOC information or
92 NULL if it failed. Argument is a name (of a network or a machine)
93 and a boolean telling is it is a network name or a machine name.
96 getlocbyname (name
, is_network
)
101 struct list_in_addr
*list
, *p
;
102 result
= findRR (name
, T_LOC
);
106 printf ("LOC record found for the name %s\n", name
);
115 printf ("No LOC record found for the name %s, trying addresses\n", name
);
118 for (p
= list
; p
!= NULL
; p
= p
->next
)
121 printf ("Trying address %s\n", inet_ntoa (p
->addr
));
122 result
= getlocbyaddr (p
->addr
, NULL
);
131 printf (" No A record found for %s\n", name
);
138 printf ("No LOC record found for the network name %s\n", name
);
145 Returns a human-readable version of the LOC information or
146 NULL if it failed. Argument is an IP address.
149 getlocbyaddr (addr
, mask
)
150 const struct in_addr addr
;
151 const struct in_addr
*mask
;
153 struct in_addr netaddr
;
155 struct in_addr themask
;
156 char text_addr
[sizeof("255.255.255.255")],
157 text_mask
[sizeof("255.255.255.255")];
161 themask
.s_addr
= (u_int32_t
) 0;
168 strcpy (text_addr
, inet_ntoa (addr
));
169 strcpy (text_mask
, inet_ntoa (themask
));
172 printf ("Testing address %s/%s\n", text_addr
, text_mask
);
176 a
= ntohl (addr
.s_addr
);
179 netaddr
.s_addr
= htonl (a
& IN_CLASSA_NET
);
180 themask
.s_addr
= htonl(IN_CLASSA_NET
);
182 else if (IN_CLASSB (a
))
184 netaddr
.s_addr
= htonl (a
& IN_CLASSB_NET
);
185 themask
.s_addr
= htonl(IN_CLASSB_NET
);
187 else if (IN_CLASSC (a
))
189 netaddr
.s_addr
= htonl (a
& IN_CLASSC_NET
);
190 themask
.s_addr
= htonl(IN_CLASSC_NET
);
197 return getlocbynet (in_addr_arpa (inet_ntoa (netaddr
)), addr
, &themask
);
201 netaddr
.s_addr
= addr
.s_addr
& themask
.s_addr
;
202 return getlocbynet (in_addr_arpa (inet_ntoa (netaddr
)), addr
, mask
);
207 Returns a human-readable LOC.
208 Argument is a network name in the 0.z.y.x.in-addr.arpa format
209 and the original address
212 getlocbynet (name
, addr
, mask
)
215 struct in_addr
*mask
;
219 struct list_in_addr
*list
;
220 struct in_addr newmask
;
222 char newname
[4 * 4 + sizeof (ARPA_ROOT
) + 2];
225 printf ("Testing network %s with mask %s\n", name
, inet_ntoa(*mask
));
227 /* Check if this network has an A RR */
231 /* Yes, it does. This A record will be used as the
232 * new mask for recursion if it is longer than
233 * the actual mask. */
234 if (mask
!= NULL
&& mask
->s_addr
< list
->addr
.s_addr
)
236 /* compute the new arguments for recursion
237 * - compute the new network by applying the new mask
238 * to the address and get the in_addr_arpa representation
240 * - the address remains unchanged
241 * - the new mask is the one given in the A record
243 a
= ntohl(addr
.s_addr
); /* start from host address */
244 a
&= ntohl(list
->addr
.s_addr
); /* apply new mask */
245 newname
[sizeof newname
- 1] = 0;
248 in_addr_arpa(inet_ntoa(inet_makeaddr(a
, 0))),
250 newmask
= inet_makeaddr(ntohl(list
->addr
.s_addr
), 0);
251 result
= getlocbynet (newname
, addr
, &newmask
);
257 /* couldn't find a LOC. Fall through and try with name */
260 /* Check if this network has a name */
261 network
= findRR (name
, T_PTR
);
265 printf ("No name for network %s\n", name
);
270 return getlocbyname (network
, TRUE
);
275 The code for these two functions is stolen from the examples in Liu and Albitz
276 book "DNS and BIND" (O'Reilly).
279 /****************************************************************
280 * skipName -- This routine skips over a domain name. If the *
281 * domain name expansion fails, it crashes. *
282 * dn_skipname() is probably not on your manual *
283 * page; it is similar to dn_expand() except that it just *
284 * skips over the name. dn_skipname() is in res_comp.c if *
285 * you need to find it. *
286 ****************************************************************/
288 skipName (cp
, endOfMsg
)
294 if ((n
= dn_skipname (cp
, endOfMsg
)) < 0)
296 panic ("dn_skipname failed\n");
301 /****************************************************************
302 * skipToData -- This routine advances the cp pointer to the *
303 * start of the resource record data portion. On the way, *
304 * it fills in the type, class, ttl, and data length *
305 ****************************************************************/
307 skipToData (cp
, type
, class, ttl
, dlen
, endOfMsg
)
315 u_char
*tmp_cp
= cp
; /* temporary version of cp */
317 /* Skip the domain name; it matches the name we looked up */
318 tmp_cp
+= skipName (tmp_cp
, endOfMsg
);
321 * Grab the type, class, and ttl. GETSHORT and GETLONG
322 * are macros defined in arpa/nameser.h.
324 GETSHORT (*type
, tmp_cp
);
325 GETSHORT (*class, tmp_cp
);
326 GETLONG (*ttl
, tmp_cp
);
327 GETSHORT (*dlen
, tmp_cp
);
329 return (tmp_cp
- cp
);
334 Returns a human-readable version of a DNS RR (resource record)
335 associated with the name 'domain'.
336 If it does not find, ir returns NULL and sets rr_errno to explain why.
338 The code for this function is stolen from the examples in Liu and Albitz
339 book "DNS and BIND" (O'Reilly).
342 findRR (domain
, requested_type
)
346 char *result
, *message
;
350 HEADER hdr
; /* defined in resolv.h */
351 u_char buf
[PACKETSZ
]; /* defined in arpa/nameser.h */
353 response
; /* response buffers */
355 int responseLen
; /* buffer length */
357 u_char
*cp
; /* character pointer to parse DNS packet */
358 u_char
*endOfMsg
; /* need to know the end of the message */
359 u_short
class; /* classes defined in arpa/nameser.h */
360 u_short type
; /* types defined in arpa/nameser.h */
361 u_int32_t ttl
; /* resource record time to live */
362 u_short dlen
; /* size of resource record data */
364 int i
, count
, dup
; /* misc variables */
370 result
= (char *) malloc (256);
371 message
= (char *) malloc (256);
373 * Look up the records for the given domain name.
374 * We expect the domain to be a fully qualified name, so
375 * we use res_query(). If we wanted the resolver search
376 * algorithm, we would have used res_search() instead.
379 res_query (domain
, /* the domain we care about */
380 C_IN
, /* Internet class records */
381 requested_type
, /* Look up name server records */
382 (u_char
*) & response
, /*response buffer */
383 sizeof (response
))) /*buffer size */
391 * Keep track of the end of the message so we don't
392 * pass it while parsing the response. responseLen is
393 * the value returned by res_query.
395 endOfMsg
= response
.buf
+ responseLen
;
398 * Set a pointer to the start of the question section,
399 * which begins immediately AFTER the header.
401 cp
= response
.buf
+ sizeof (HEADER
);
404 * Skip over the whole question section. The question
405 * section is comprised of a name, a type, and a class.
406 * QFIXEDSZ (defined in arpa/nameser.h) is the size of
407 * the type and class portions, which is fixed. Therefore,
408 * we can skip the question section by skipping the
409 * name (at the beginning) and then advancing QFIXEDSZ.
410 * After this calculation, cp points to the start of the
411 * answer section, which is a list of NS records.
413 cp
+= skipName (cp
, endOfMsg
) + QFIXEDSZ
;
415 count
= ntohs (response
.hdr
.ancount
) +
416 ntohs (response
.hdr
.nscount
);
417 while ((--count
>= 0) /* still more records */
419 { /* still inside the packet */
422 /* Skip to the data portion of the resource record */
423 cp
+= skipToData (cp
, &type
, &class, &ttl
, &dlen
, endOfMsg
);
425 if (type
== requested_type
)
427 switch (requested_type
)
430 loc_ntoa (cp
, result
);
434 ptrList
[ptrNum
] = (char *) malloc (MAXDNAME
);
435 if (ptrList
[ptrNum
] == NULL
)
437 panic ("Malloc failed");
440 if (dn_expand (response
.buf
, /* Start of the packet */
441 endOfMsg
, /* End of the packet */
442 cp
, /* Position in the packet */
443 (char *) ptrList
[ptrNum
], /* Result */
444 MAXDNAME
) /* size of ptrList buffer */
446 { /* Negative: error */
447 panic ("dn_expand failed");
451 * Check the name we've just unpacked and add it to
452 * the list if it is not a duplicate.
453 * If it is a duplicate, just ignore it.
455 for (i
= 0, dup
= 0; (i
< ptrNum
) && !dup
; i
++)
456 dup
= !strcasecmp (ptrList
[i
], ptrList
[ptrNum
]);
458 free (ptrList
[ptrNum
]);
461 strcpy (result
, ptrList
[0]);
465 bcopy ((char *) cp
, (char *) &addr
, INADDRSZ
);
466 strcat (result
, " ");
467 strcat (result
, inet_ntoa (addr
));
471 sprintf (message
, "Unexpected type %u", requested_type
);
476 /* Advance the pointer over the resource record data */
486 struct list_in_addr
*
491 struct list_in_addr
*result
, *end
;
495 HEADER hdr
; /* defined in resolv.h */
496 u_char buf
[PACKETSZ
]; /* defined in arpa/nameser.h */
498 response
; /* response buffers */
499 int responseLen
; /* buffer length */
501 u_char
*cp
; /* character pointer to parse DNS packet */
502 u_char
*endOfMsg
; /* need to know the end of the message */
503 u_short
class; /* classes defined in arpa/nameser.h */
504 u_short type
; /* types defined in arpa/nameser.h */
505 u_int32_t ttl
; /* resource record time to live */
506 u_short dlen
; /* size of resource record data */
508 int count
; /* misc variables */
516 * Look up the records for the given domain name.
517 * We expect the domain to be a fully qualified name, so
518 * we use res_query(). If we wanted the resolver search
519 * algorithm, we would have used res_search() instead.
522 res_query (domain
, /* the domain we care about */
523 C_IN
, /* Internet class records */
525 (u_char
*) & response
, /*response buffer */
526 sizeof (response
))) /*buffer size */
534 * Keep track of the end of the message so we don't
535 * pass it while parsing the response. responseLen is
536 * the value returned by res_query.
538 endOfMsg
= response
.buf
+ responseLen
;
541 * Set a pointer to the start of the question section,
542 * which begins immediately AFTER the header.
544 cp
= response
.buf
+ sizeof (HEADER
);
547 * Skip over the whole question section. The question
548 * section is comprised of a name, a type, and a class.
549 * QFIXEDSZ (defined in arpa/nameser.h) is the size of
550 * the type and class portions, which is fixed. Therefore,
551 * we can skip the question section by skipping the
552 * name (at the beginning) and then advancing QFIXEDSZ.
553 * After this calculation, cp points to the start of the
554 * answer section, which is a list of NS records.
556 cp
+= skipName (cp
, endOfMsg
) + QFIXEDSZ
;
558 count
= ntohs (response
.hdr
.ancount
) +
559 ntohs (response
.hdr
.nscount
);
560 while ((--count
>= 0) /* still more records */
562 { /* still inside the packet */
565 /* Skip to the data portion of the resource record */
566 cp
+= skipToData (cp
, &type
, &class, &ttl
, &dlen
, endOfMsg
);
570 bcopy ((char *) cp
, (char *) &addr
, INADDRSZ
);
573 result
= (void *) malloc (sizeof (struct list_in_addr
));
580 end
->next
= (void *) malloc (sizeof (struct list_in_addr
));
587 /* Advance the pointer over the resource record data */