]> Git Repo - uclibc-ng.git/blob - libc/inet/resolv.c
patch from Jari Korva <[email protected]>:
[uclibc-ng.git] / libc / inet / resolv.c
1 /* resolv.c: DNS Resolver
2  *
3  * Copyright (C) 1998  Kenneth Albanowski <[email protected]>,
4  *                     The Silver Hammer Group, Ltd.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  *  5-Oct-2000 W. Greathouse  [email protected]
12  *                              Fix memory leak and memory corruption.
13  *                              -- Every name resolution resulted in
14  *                                 a new parse of resolv.conf and new
15  *                                 copy of nameservers allocated by
16  *                                 strdup.
17  *                              -- Every name resolution resulted in
18  *                                 a new read of resolv.conf without
19  *                                 resetting index from prior read...
20  *                                 resulting in exceeding array bounds.
21  *
22  *                              Limit nameservers read from resolv.conf
23  *
24  *                              Add "search" domains from resolv.conf
25  *
26  *                              Some systems will return a security
27  *                              signature along with query answer for
28  *                              dynamic DNS entries.
29  *                              -- skip/ignore this answer
30  *
31  *                              Include arpa/nameser.h for defines.
32  *
33  *                              General cleanup
34  *
35  * 20-Jun-2001 Michal Moskal <[email protected]>
36  *   partial IPv6 support (i.e. gethostbyname2() and resolve_address2()
37  *   functions added), IPv6 nameservers are also supported.
38  *
39  * 6-Oct-2001 Jari Korva <[email protected]>
40  *   more IPv6 support (IPv6 support for gethostbyaddr();
41  *   address family parameter and improved IPv6 support for get_hosts_byname
42  *   and read_etc_hosts; getnameinfo() port from glibc; defined
43  *   defined ip6addr_any and in6addr_loopback)
44  */
45
46 #define __FORCE_GLIBC
47 #include <features.h>
48 #include <string.h>
49 #include <stdio.h>
50 #include <signal.h>
51 #include <errno.h>
52 #include <sys/socket.h>
53 #include <sys/types.h>
54 #include <netinet/in.h>
55 #include <arpa/inet.h>
56 #include <stdlib.h>
57 #include <unistd.h>
58 #include <resolv.h>
59 #include <netdb.h>
60 #include <ctype.h>
61 #include <arpa/nameser.h>
62 #include <sys/utsname.h>
63 #include <sys/un.h>
64
65 #define MAX_RECURSE 5
66 #define REPLY_TIMEOUT 10
67 #define MAX_RETRIES 15
68 #define MAX_SERVERS 3
69 #define MAX_SEARCH 4
70
71 #undef DEBUG
72 /*#define DEBUG*/
73
74 #ifdef DEBUG
75 #define DPRINTF(X,args...) fprintf(stderr, X, ##args)
76 #else
77 #define DPRINTF(X,args...)
78 #endif /* DEBUG */
79
80
81 struct resolv_header {
82         int id;
83         int qr,opcode,aa,tc,rd,ra,rcode;
84         int qdcount;
85         int ancount;
86         int nscount;
87         int arcount;
88 };
89
90 struct resolv_question {
91         char * dotted;
92         int qtype;
93         int qclass;
94 };
95
96 struct resolv_answer {
97         char * dotted;
98         int atype;
99         int aclass;
100         int ttl;
101         int rdlength;
102         unsigned char * rdata;
103         int rdoffset;
104 };
105
106 extern int nameservers;
107 extern char * nameserver[MAX_SERVERS];
108 extern int searchdomains;
109 extern char * searchdomain[MAX_SEARCH];
110 extern struct hostent * get_hosts_byname(const char * name, int type);
111 extern struct hostent * get_hosts_byaddr(const char * addr, int len, int type);
112 extern struct hostent * read_etc_hosts(const char * name, int type, int ip);
113 extern int resolve_address(const char * address, int nscount, 
114         char ** nsip, struct in_addr * in);
115 extern int resolve_mailbox(const char * address, int nscount, 
116         char ** nsip, struct in_addr * in);
117 extern int dns_lookup(const char * name, int type, int nscount, 
118         char ** nsip, unsigned char ** outpacket, struct resolv_answer * a);
119
120 int encode_dotted(const char * dotted, unsigned char * dest, int maxlen);
121 int decode_dotted(const unsigned char * message, int offset, 
122         char * dest, int maxlen);
123 int length_dotted(const unsigned char * message, int offset);
124 int encode_header(struct resolv_header * h, unsigned char * dest, int maxlen);
125 int decode_header(unsigned char * data, struct resolv_header * h);
126 int encode_question(struct resolv_question * q,
127         unsigned char * dest, int maxlen);
128 int decode_question(unsigned char * message, int offset,
129         struct resolv_question * q);
130 int encode_answer(struct resolv_answer * a,
131         unsigned char * dest, int maxlen);
132 int decode_answer(unsigned char * message, int offset,
133         struct resolv_answer * a);
134 int length_question(unsigned char * message, int offset);
135 extern int open_nameservers(void);
136
137
138 #ifdef L_encodeh
139 int encode_header(struct resolv_header *h, unsigned char *dest, int maxlen)
140 {
141         if (maxlen < HFIXEDSZ)
142                 return -1;
143
144         dest[0] = (h->id & 0xff00) >> 8;
145         dest[1] = (h->id & 0x00ff) >> 0;
146         dest[2] = (h->qr ? 0x80 : 0) |
147                 ((h->opcode & 0x0f) << 3) |
148                 (h->aa ? 0x04 : 0) | 
149                 (h->tc ? 0x02 : 0) | 
150                 (h->rd ? 0x01 : 0);
151         dest[3] = (h->ra ? 0x80 : 0) | (h->rcode & 0x0f);
152         dest[4] = (h->qdcount & 0xff00) >> 8;
153         dest[5] = (h->qdcount & 0x00ff) >> 0;
154         dest[6] = (h->ancount & 0xff00) >> 8;
155         dest[7] = (h->ancount & 0x00ff) >> 0;
156         dest[8] = (h->nscount & 0xff00) >> 8;
157         dest[9] = (h->nscount & 0x00ff) >> 0;
158         dest[10] = (h->arcount & 0xff00) >> 8;
159         dest[11] = (h->arcount & 0x00ff) >> 0;
160
161         return HFIXEDSZ;
162 }
163 #endif
164
165 #ifdef L_decodeh
166 int decode_header(unsigned char *data, struct resolv_header *h)
167 {
168         h->id = (data[0] << 8) | data[1];
169         h->qr = (data[2] & 0x80) ? 1 : 0;
170         h->opcode = (data[2] >> 3) & 0x0f;
171         h->aa = (data[2] & 0x04) ? 1 : 0;
172         h->tc = (data[2] & 0x02) ? 1 : 0;
173         h->rd = (data[2] & 0x01) ? 1 : 0;
174         h->ra = (data[3] & 0x80) ? 1 : 0;
175         h->rcode = data[3] & 0x0f;
176         h->qdcount = (data[4] << 8) | data[5];
177         h->ancount = (data[6] << 8) | data[7];
178         h->nscount = (data[8] << 8) | data[9];
179         h->arcount = (data[10] << 8) | data[11];
180
181         return HFIXEDSZ;
182 }
183 #endif
184
185 #ifdef L_encoded
186 /* Encode a dotted string into nameserver transport-level encoding.
187    This routine is fairly dumb, and doesn't attempt to compress
188    the data */
189
190 int encode_dotted(const char *dotted, unsigned char *dest, int maxlen)
191 {
192         int used = 0;
193
194         while (dotted && *dotted) {
195                 char *c = strchr(dotted, '.');
196                 int l = c ? c - dotted : strlen(dotted);
197
198                 if (l >= (maxlen - used - 1))
199                         return -1;
200
201                 dest[used++] = l;
202                 memcpy(dest + used, dotted, l);
203                 used += l;
204
205                 if (c)
206                         dotted = c + 1;
207                 else
208                         break;
209         }
210
211         if (maxlen < 1)
212                 return -1;
213
214         dest[used++] = 0;
215
216         return used;
217 }
218 #endif
219
220 #ifdef L_decoded
221 /* Decode a dotted string from nameserver transport-level encoding.
222    This routine understands compressed data. */
223
224 int decode_dotted(const unsigned char *data, int offset,
225                                   char *dest, int maxlen)
226 {
227         int l;
228         int measure = 1;
229         int total = 0;
230         int used = 0;
231
232         if (!data)
233                 return -1;
234
235         while ((l=data[offset++])) {
236                 if (measure)
237                     total++;
238                 if ((l & 0xc0) == (0xc0)) {
239                         if (measure)
240                                 total++;
241                         /* compressed item, redirect */
242                         offset = ((l & 0x3f) << 8) | data[offset];
243                         measure = 0;
244                         continue;
245                 }
246
247                 if ((used + l + 1) >= maxlen)
248                         return -1;
249
250                 memcpy(dest + used, data + offset, l);
251                 offset += l;
252                 used += l;
253                 if (measure)
254                         total += l;
255
256                 if (data[offset] != 0)
257                         dest[used++] = '.';
258                 else
259                         dest[used++] = '\0';
260         }
261
262         DPRINTF("Total decode len = %d\n", total);
263
264         return total;
265 }
266 #endif
267
268 #ifdef L_lengthd
269
270 int length_dotted(const unsigned char *data, int offset)
271 {
272         int orig_offset = offset;
273         int l;
274
275         if (!data)
276                 return -1;
277
278         while ((l = data[offset++])) {
279
280                 if ((l & 0xc0) == (0xc0)) {
281                         offset++;
282                         break;
283                 }
284
285                 offset += l;
286         }
287
288         return offset - orig_offset;
289 }
290 #endif
291
292 #ifdef L_encodeq
293 int encode_question(struct resolv_question *q,
294                                         unsigned char *dest, int maxlen)
295 {
296         int i;
297
298         i = encode_dotted(q->dotted, dest, maxlen);
299         if (i < 0)
300                 return i;
301
302         dest += i;
303         maxlen -= i;
304
305         if (maxlen < 4)
306                 return -1;
307
308         dest[0] = (q->qtype & 0xff00) >> 8;
309         dest[1] = (q->qtype & 0x00ff) >> 0;
310         dest[2] = (q->qclass & 0xff00) >> 8;
311         dest[3] = (q->qclass & 0x00ff) >> 0;
312
313         return i + 4;
314 }
315 #endif
316
317 #ifdef L_decodeq
318 int decode_question(unsigned char *message, int offset,
319                                         struct resolv_question *q)
320 {
321         char temp[256];
322         int i;
323
324         i = decode_dotted(message, offset, temp, sizeof(temp));
325         if (i < 0)
326                 return i;
327
328         offset += i;
329
330         q->dotted = strdup(temp);
331         q->qtype = (message[offset + 0] << 8) | message[offset + 1];
332         q->qclass = (message[offset + 2] << 8) | message[offset + 3];
333
334         return i + 4;
335 }
336 #endif
337
338 #ifdef L_lengthq
339 int length_question(unsigned char *message, int offset)
340 {
341         int i;
342
343         i = length_dotted(message, offset);
344         if (i < 0)
345                 return i;
346
347         return i + 4;
348 }
349 #endif
350
351 #ifdef L_encodea
352 int encode_answer(struct resolv_answer *a, unsigned char *dest, int maxlen)
353 {
354         int i;
355
356         i = encode_dotted(a->dotted, dest, maxlen);
357         if (i < 0)
358                 return i;
359
360         dest += i;
361         maxlen -= i;
362
363         if (maxlen < (RRFIXEDSZ+a->rdlength))
364                 return -1;
365
366         *dest++ = (a->atype & 0xff00) >> 8;
367         *dest++ = (a->atype & 0x00ff) >> 0;
368         *dest++ = (a->aclass & 0xff00) >> 8;
369         *dest++ = (a->aclass & 0x00ff) >> 0;
370         *dest++ = (a->ttl & 0xff000000) >> 24;
371         *dest++ = (a->ttl & 0x00ff0000) >> 16;
372         *dest++ = (a->ttl & 0x0000ff00) >> 8;
373         *dest++ = (a->ttl & 0x000000ff) >> 0;
374         *dest++ = (a->rdlength & 0xff00) >> 8;
375         *dest++ = (a->rdlength & 0x00ff) >> 0;
376         memcpy(dest, a->rdata, a->rdlength);
377
378         return i + RRFIXEDSZ + a->rdlength;
379 }
380 #endif
381
382 #ifdef L_decodea
383 int decode_answer(unsigned char *message, int offset,
384                                   struct resolv_answer *a)
385 {
386         char temp[256];
387         int i;
388
389         i = decode_dotted(message, offset, temp, sizeof(temp));
390         if (i < 0)
391                 return i;
392
393         message += offset + i;
394
395         a->dotted = strdup(temp);
396         a->atype = (message[0] << 8) | message[1];
397         message += 2;
398         a->aclass = (message[0] << 8) | message[1];
399         message += 2;
400         a->ttl = (message[0] << 24) |
401                 (message[1] << 16) | (message[2] << 8) | (message[3] << 0);
402         message += 4;
403         a->rdlength = (message[0] << 8) | message[1];
404         message += 2;
405         a->rdata = message;
406         a->rdoffset = offset + i + RRFIXEDSZ;
407
408         DPRINTF("i=%d,rdlength=%d\n", i, a->rdlength);
409
410         return i + RRFIXEDSZ + a->rdlength;
411 }
412 #endif
413
414 #ifdef L_encodep
415 int encode_packet(struct resolv_header *h,
416         struct resolv_question **q,
417         struct resolv_answer **an,
418         struct resolv_answer **ns,
419         struct resolv_answer **ar,
420         unsigned char *dest, int maxlen)
421 {
422         int i, total = 0;
423         int j;
424
425         i = encode_header(h, dest, maxlen);
426         if (i < 0)
427                 return i;
428
429         dest += i;
430         maxlen -= i;
431         total += i;
432
433         for (j = 0; j < h->qdcount; j++) {
434                 i = encode_question(q[j], dest, maxlen);
435                 if (i < 0)
436                         return i;
437                 dest += i;
438                 maxlen -= i;
439                 total += i;
440         }
441
442         for (j = 0; j < h->ancount; j++) {
443                 i = encode_answer(an[j], dest, maxlen);
444                 if (i < 0)
445                         return i;
446                 dest += i;
447                 maxlen -= i;
448                 total += i;
449         }
450         for (j = 0; j < h->nscount; j++) {
451                 i = encode_answer(ns[j], dest, maxlen);
452                 if (i < 0)
453                         return i;
454                 dest += i;
455                 maxlen -= i;
456                 total += i;
457         }
458         for (j = 0; j < h->arcount; j++) {
459                 i = encode_answer(ar[j], dest, maxlen);
460                 if (i < 0)
461                         return i;
462                 dest += i;
463                 maxlen -= i;
464                 total += i;
465         }
466
467         return total;
468 }
469 #endif
470
471 #ifdef L_decodep
472 int decode_packet(unsigned char *data, struct resolv_header *h)
473 {
474         return decode_header(data, h);
475 }
476 #endif
477
478 #ifdef L_formquery
479 int form_query(int id, const char *name, int type, unsigned char *packet,
480                            int maxlen)
481 {
482         struct resolv_header h;
483         struct resolv_question q;
484         int i, j;
485
486         memset(&h, 0, sizeof(h));
487         h.id = id;
488         h.qdcount = 1;
489
490         q.dotted = (char *) name;
491         q.qtype = type;
492         q.qclass = C_IN; /* CLASS_IN */
493
494         i = encode_header(&h, packet, maxlen);
495         if (i < 0)
496                 return i;
497
498         j = encode_question(&q, packet + i, maxlen - i);
499         if (j < 0)
500                 return j;
501
502         return i + j;
503 }
504 #endif
505
506 #ifdef L_dnslookup
507
508 int dns_caught_signal = 0;
509 void dns_catch_signal(int signo)
510 {
511         dns_caught_signal = 1;
512 }
513
514 int dns_lookup(const char *name, int type, int nscount, char **nsip,
515                            unsigned char **outpacket, struct resolv_answer *a)
516 {
517         static int id = 1;
518         int i, j, len, fd, pos;
519         static int ns = 0;
520         struct sockaddr_in sa;
521 #ifdef __UCLIBC_HAS_IPV6__
522         struct sockaddr_in6 sa6;
523 #endif /* __UCLIBC_HAS_IPV6__ */
524         int oldalarm;
525         __sighandler_t oldhandler;
526         struct resolv_header h;
527         struct resolv_question q;
528         int retries = 0;
529         unsigned char * packet = malloc(PACKETSZ);
530         unsigned char * lookup = malloc(MAXDNAME);
531         int variant = 0;
532 #ifdef __UCLIBC_HAS_IPV6__
533         int v6;
534 #endif /* __UCLIBC_HAS_IPV6__ */
535
536         fd = -1;
537
538         if (!packet || !lookup || !nscount)
539             goto fail;
540
541         DPRINTF("Looking up type %d answer for '%s'\n", type, name);
542
543         ns %= nscount;
544
545         while (retries++ < MAX_RETRIES) {
546 #ifdef __UCLIBC_HAS_IPV6__
547                 v6 = (inet_pton(AF_INET6, nsip[ns], &sa6.sin6_addr) > 0);
548 #endif /* __UCLIBC_HAS_IPV6__ */
549
550                 if (fd != -1)
551                         close(fd);
552
553 #ifndef __UCLIBC_HAS_IPV6__
554                 fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
555 #else /* __UCLIBC_HAS_IPV6__ */
556                 fd = socket(v6 ? AF_INET6 : AF_INET, SOCK_DGRAM, IPPROTO_UDP);
557 #endif /* __UCLIBC_HAS_IPV6__ */
558
559                 if (fd == -1)
560                         goto fail;
561
562                 memset(packet, 0, PACKETSZ);
563
564                 memset(&h, 0, sizeof(h));
565                 h.id = ++id;
566                 h.qdcount = 1;
567                 h.rd = 1;
568
569                 DPRINTF("encoding header\n", h.rd);
570
571                 i = encode_header(&h, packet, PACKETSZ);
572                 if (i < 0)
573                         goto fail;
574
575                 strncpy(lookup,name,MAXDNAME);
576                 if (variant < searchdomains && strchr(lookup, '.') == NULL)
577                 {
578                     strncat(lookup,".", MAXDNAME);
579                     strncat(lookup,searchdomain[variant], MAXDNAME);
580                 }
581                 DPRINTF("lookup name: %s\n", lookup);
582                 q.dotted = (char *)lookup;
583                 q.qtype = type;
584                 q.qclass = C_IN; /* CLASS_IN */
585
586                 j = encode_question(&q, packet+i, PACKETSZ-i);
587                 if (j < 0)
588                         goto fail;
589
590                 len = i + j;
591
592                 DPRINTF("On try %d, sending query to port %d of machine %s\n",
593                                 retries, NAMESERVER_PORT, nsip[ns]);
594
595 #ifndef __UCLIBC_HAS_IPV6__
596                 sa.sin_family = AF_INET;
597                 sa.sin_port = htons(NAMESERVER_PORT);
598                 sa.sin_addr.s_addr = inet_addr(nsip[ns]);
599 #else /* __UCLIBC_HAS_IPV6__ */
600                 if (v6) {
601                         sa6.sin6_family = AF_INET6;
602                         sa6.sin6_port = htons(NAMESERVER_PORT);
603                         /* sa6.sin6_addr is already here */
604                 } else {
605                         sa.sin_family = AF_INET;
606                         sa.sin_port = htons(NAMESERVER_PORT);
607                         sa.sin_addr.s_addr = inet_addr(nsip[ns]);
608                 }
609 #endif /* __UCLIBC_HAS_IPV6__ */
610
611 #ifndef __UCLIBC_HAS_IPV6__
612                 if (connect(fd, (struct sockaddr *) &sa, sizeof(sa)) == -1) {
613 #else /* __UCLIBC_HAS_IPV6__ */
614                 if (connect(fd, (struct sockaddr *) (v6 ? &sa6 : &sa), 
615                             v6 ? sizeof(sa6) : sizeof(sa)) == -1) {
616 #endif /* __UCLIBC_HAS_IPV6__ */
617                         if (errno == ENETUNREACH) {
618                                 /* routing error, presume not transient */
619                                 goto tryall;
620                         } else
621                                 /* retry */
622                                 continue;
623                 }
624
625                 DPRINTF("Transmitting packet of length %d, id=%d, qr=%d\n",
626                                 len, h.id, h.qr);
627
628                 send(fd, packet, len, 0);
629
630                 dns_caught_signal = 0;
631                 oldalarm = alarm(REPLY_TIMEOUT);
632                 oldhandler = signal(SIGALRM, dns_catch_signal);
633
634                 i = recv(fd, packet, PACKETSZ, 0);
635
636                 alarm(0);
637                 signal(SIGALRM, oldhandler);
638                 alarm(oldalarm);
639
640                 DPRINTF("Timeout=%d, len=%d\n", dns_caught_signal, i);
641
642                 if (dns_caught_signal)
643                         /* timed out, so retry send and receive,
644                            to next nameserver on queue */
645                         goto again;
646
647                 if (i < HFIXEDSZ)
648                         /* too short ! */
649                         goto again;
650
651                 decode_header(packet, &h);
652
653                 DPRINTF("id = %d, qr = %d\n", h.id, h.qr);
654
655                 if ((h.id != id) || (!h.qr))
656                         /* unsolicited */
657                         goto again;
658
659                 DPRINTF("Got response %s\n", "(i think)!");
660                 DPRINTF("qrcount=%d,ancount=%d,nscount=%d,arcount=%d\n",
661                                 h.qdcount, h.ancount, h.nscount, h.arcount);
662                 DPRINTF("opcode=%d,aa=%d,tc=%d,rd=%d,ra=%d,rcode=%d\n",
663                                 h.opcode, h.aa, h.tc, h.rd, h.ra, h.rcode);
664
665                 if ((h.rcode) || (h.ancount < 1)) {
666                         /* negative result, not present */
667                         goto again;
668                 }
669
670                 pos = HFIXEDSZ;
671
672                 for (j = 0; j < h.qdcount; j++) {
673                         DPRINTF("Skipping question %d at %d\n", j, pos);
674                         i = length_question(packet, pos);
675                         DPRINTF("Length of question %d is %d\n", j, i);
676                         if (i < 0)
677                                 goto again;
678                         pos += i;
679                 }
680                 DPRINTF("Decoding answer at pos %d\n", pos);
681
682                 for (j=0;j<h.ancount;j++)
683                 {
684                     i = decode_answer(packet, pos, a);
685
686                     if (i<0) {
687                         DPRINTF("failed decode %d\n", i);
688                         goto again;
689                     }
690                     /* For all but T_SIG, accept first answer */
691                     if (a->atype != T_SIG)
692                         break;
693
694                     DPRINTF("skipping T_SIG %d\n", i);
695                     free(a->dotted);
696                     pos += i;
697                 }
698
699                 DPRINTF("Answer name = |%s|\n", a->dotted);
700                 DPRINTF("Answer type = |%d|\n", a->atype);
701
702                 close(fd);
703
704                 if (outpacket)
705                         *outpacket = packet;
706                 else
707                         free(packet);
708                 free(lookup);
709                 return (0);                             /* success! */
710
711           tryall:
712                 /* if there are other nameservers, give them a go,
713                    otherwise return with error */
714                 variant = 0;
715                 if (retries >= nscount*(searchdomains+1))
716                     goto fail;
717
718           again:
719                 /* if there are searchdomains, try them or fallback as passed */
720                 if (variant < searchdomains) {
721                     /* next search */
722                     variant++;
723                 } else {
724                     /* next server, first search */
725                     ns = (ns + 1) % nscount;
726                     variant = 0;
727                 }
728         }
729
730 fail:
731         if (fd != -1)
732             close(fd);
733         if (lookup)
734             free(lookup);
735         if (packet)
736             free(packet);
737         return -1;
738 }
739 #endif
740
741 #ifdef L_resolveaddress
742
743 int resolve_address(const char *address, int nscount, 
744         char **nsip, struct in_addr *in)
745 {
746         unsigned char *packet;
747         struct resolv_answer a;
748         char temp[256];
749         int i;
750         int nest = 0;
751
752         if (!address || !in)
753                 return -1;
754
755         strncpy(temp, address, sizeof(temp));
756
757         for (;;) {
758
759                 i = dns_lookup(temp, T_A, nscount, nsip, &packet, &a);
760
761                 if (i < 0)
762                         return -1;
763
764                 free(a.dotted);
765
766                 if (a.atype == T_CNAME) {               /* CNAME */
767                         DPRINTF("Got a CNAME in resolve_address()\n");
768                         i = decode_dotted(packet, a.rdoffset, temp, sizeof(temp));
769                         free(packet);
770
771                         if (i < 0)
772                                 return -1;
773                         if (++nest > MAX_RECURSE)
774                                 return -1;
775                         continue;
776                 } else if (a.atype == T_A) {    /* ADDRESS */
777                         free(packet);
778                         break;
779                 } else {
780                         free(packet);
781                         return -1;
782                 }
783         }
784
785         if (in)
786             memcpy(in, a.rdata, INADDRSZ); /* IPv4 T_A */
787
788         return 0;
789 }
790 #endif
791
792 #ifdef L_resolvemailbox
793
794 int resolve_mailbox(const char *address, int nscount, 
795         char **nsip, struct in_addr *in)
796 {
797         struct resolv_answer a;
798         unsigned char *packet;
799         char temp[256];
800         int nest = 0;
801         int i;
802
803         if (!address || !in)
804                 return -1;
805
806         /* look up mail exchange */
807         i = dns_lookup(address, T_MX, nscount, nsip, &packet, &a);
808
809         strncpy(temp, address, sizeof(temp));
810
811         if (i >= 0) {
812                 i = decode_dotted(packet, a.rdoffset+2, temp, sizeof(temp));
813                 free(packet);
814         }
815
816         for (;;) {
817
818                 i = dns_lookup(temp, T_A, nscount, nsip, &packet, &a);
819
820                 if (i < 0)
821                         return -1;
822
823                 free(a.dotted);
824
825                 if (a.atype == T_CNAME) {               /* CNAME */
826                         DPRINTF("Got a CNAME in resolve_mailbox()\n");
827                         i = decode_dotted(packet, a.rdoffset, temp, sizeof(temp));
828                         free(packet);
829                         if (i < 0)
830                                 return i;
831                         if (++nest > MAX_RECURSE)
832                                 return -1;
833                         continue;
834                 } else if (a.atype == T_A) {    /* ADDRESS */
835                         free(packet);
836                         break;
837                 } else {
838                         free(packet);
839                         return -1;
840                 }
841         }
842
843         if (in)
844                 memcpy(in, a.rdata, INADDRSZ); /* IPv4 */
845
846         return 0;
847 }
848 #endif
849
850
851 #ifdef L_opennameservers
852
853 int nameservers;
854 char * nameserver[MAX_SERVERS];
855 int searchdomains;
856 char * searchdomain[MAX_SEARCH];
857
858 /*
859  *      we currently read formats not quite the same as that on normal
860  *      unix systems, we can have a list of nameservers after the keyword.
861  */
862
863 int open_nameservers()
864 {
865         FILE *fp;
866         int i;
867 #define RESOLV_ARGS 5
868         char szBuffer[128], *p, *argv[RESOLV_ARGS];
869         int argc;
870
871         if (nameservers > 0) 
872             return 0;
873
874         if ((fp = fopen("/etc/resolv.conf", "r")) ||
875                         (fp = fopen("/etc/config/resolv.conf", "r"))) {
876
877                 while (fgets(szBuffer, sizeof(szBuffer), fp) != NULL) {
878
879                         for (p = szBuffer; *p && isspace(*p); p++)
880                                 /* skip white space */;
881                         if (*p == '\0' || *p == '\n' || *p == '#') /* skip comments etc */
882                                 continue;
883                         argc = 0;
884                         while (*p && argc < RESOLV_ARGS) {
885                                 argv[argc++] = p;
886                                 while (*p && !isspace(*p) && *p != '\n')
887                                         p++;
888                                 while (*p && (isspace(*p) || *p == '\n')) /* remove spaces */
889                                         *p++ = '\0';
890                         }
891
892                         if (strcmp(argv[0], "nameserver") == 0) {
893                                 for (i = 1; i < argc && nameservers < MAX_SERVERS; i++) {
894                                         nameserver[nameservers++] = strdup(argv[i]);
895                                         DPRINTF("adding nameserver %s\n", argv[i]);
896                                 }
897                         }
898
899                         /* domain and search are mutually exclusive, the last one wins */
900                         if (strcmp(argv[0],"domain")==0 || strcmp(argv[0],"search")==0) {
901                                 while (searchdomains > 0) {
902                                         free(searchdomain[--searchdomains]);
903                                         searchdomain[searchdomains] = NULL;
904                                 }
905                                 for (i=1; i < argc && searchdomains < MAX_SEARCH; i++) {
906                                         searchdomain[searchdomains++] = strdup(argv[i]);
907                                         DPRINTF("adding search %s\n", argv[i]);
908                                 }
909                         }
910                 }
911                 fclose(fp);
912         } else {
913             DPRINTF("failed to open %s\n", "resolv.conf");
914         }
915         DPRINTF("nameservers = %d\n", nameservers);
916         return 0;
917 }
918 #endif
919
920
921 #ifdef L_closenameservers
922
923 void close_nameservers(void)
924 {
925         while (nameservers > 0) {
926                 free(nameserver[--nameservers]);
927                 nameserver[nameservers] = NULL;
928         }
929         while (searchdomains > 0) {
930                 free(searchdomain[--searchdomains]);
931                 searchdomain[searchdomains] = NULL;
932         }
933 }
934 #endif
935
936
937 #ifdef L_resolvename
938
939 const char *resolve_name(const char *name, int mailbox)
940 {
941         struct in_addr in;
942         int i;
943
944         /* shortcut: is it a valid IP address to begin with? */
945         if (inet_aton(name, &in))
946                 return name;
947
948         open_nameservers();
949
950         DPRINTF("looking up '%s', mailbox=%d, nameservers=%d\n",
951                         name, mailbox, nameservers);
952
953         if (mailbox)
954                 i = resolve_mailbox(name, nameservers, nameserver, &in);
955         else
956                 i = resolve_address(name, nameservers, nameserver, &in);
957
958         if (i < 0)
959                 return 0;
960
961         DPRINTF("success = '%s'\n", inet_ntoa(in));
962
963         return inet_ntoa(in);
964 }
965 #endif
966
967
968 #ifdef L_gethostbyname
969
970 struct hostent *gethostbyname(const char *name)
971 {
972         static struct hostent h;
973         static char namebuf[256];
974         static struct in_addr in;
975         static struct in_addr *addr_list[2];
976         struct hostent *hp;
977         unsigned char *packet;
978         struct resolv_answer a;
979         int i;
980         int nest = 0;
981
982         open_nameservers();
983
984         if (!name)
985                 return 0;
986
987         if ((hp = get_hosts_byname(name, AF_INET))) /* do /etc/hosts first */
988                 return(hp);
989
990         memset(&h, 0, sizeof(h));
991
992         addr_list[0] = &in;
993         addr_list[1] = 0;
994         
995         strncpy(namebuf, name, sizeof(namebuf));
996
997         /* First check if this is already an address */
998         if (inet_aton(name, &in)) {
999             h.h_name = namebuf;
1000             h.h_addrtype = AF_INET;
1001             h.h_length = sizeof(in);
1002             h.h_addr_list = (char **) addr_list;
1003             return &h;
1004         }
1005
1006         for (;;) {
1007
1008                 i = dns_lookup(namebuf, 1, nameservers, nameserver, &packet, &a);
1009
1010                 if (i < 0)
1011                         return 0;
1012
1013                 strncpy(namebuf, a.dotted, sizeof(namebuf));
1014                 free(a.dotted);
1015
1016
1017                 if (a.atype == T_CNAME) {               /* CNAME */
1018                         DPRINTF("Got a CNAME in gethostbyname()\n");
1019                         i = decode_dotted(packet, a.rdoffset, namebuf, sizeof(namebuf));
1020                         free(packet);
1021
1022                         if (i < 0)
1023                                 return 0;
1024                         if (++nest > MAX_RECURSE)
1025                                 return 0;
1026                         continue;
1027                 } else if (a.atype == T_A) {    /* ADDRESS */
1028                         memcpy(&in, a.rdata, sizeof(in));
1029                         h.h_name = namebuf;
1030                         h.h_addrtype = AF_INET;
1031                         h.h_length = sizeof(in);
1032                         h.h_addr_list = (char **) addr_list;
1033                         free(packet);
1034                         break;
1035                 } else {
1036                         free(packet);
1037                         return 0;
1038                 }
1039         }
1040
1041         return &h;
1042 }
1043 #endif
1044
1045 #ifdef L_gethostbyname2
1046
1047 #ifdef __UCLIBC_HAS_IPV6__
1048 /* TBD: Not the right place for defining these, I guess */
1049 const struct in6_addr in6addr_any =
1050         { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } };
1051 const struct in6_addr in6addr_loopback =
1052         { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } } };                                    
1053 #endif /* __UCLIBC_HAS_IPV6__ */
1054
1055 struct hostent *gethostbyname2(const char *name, int family)
1056 {
1057 #ifndef __UCLIBC_HAS_IPV6__
1058         return family == AF_INET ? gethostbyname(name) : (struct hostent*)0;
1059 #else /* __UCLIBC_HAS_IPV6__ */
1060         static struct hostent h;
1061         static char namebuf[256];
1062         static struct in6_addr in;
1063         static struct in6_addr *addr_list[2];
1064         struct hostent *hp;
1065         unsigned char *packet;
1066         struct resolv_answer a;
1067         int i;
1068         int nest = 0;
1069
1070         if (family == AF_INET)
1071                 return gethostbyname(name);
1072                 
1073         if (family != AF_INET6)
1074                 return NULL;
1075                 
1076         open_nameservers();
1077
1078         if (!name)
1079                 return 0;
1080
1081         if ((hp = get_hosts_byname(name, family))) /* do /etc/hosts first */
1082                 return(hp);
1083
1084         memset(&h, 0, sizeof(h));
1085
1086         addr_list[0] = &in;
1087         addr_list[1] = 0;
1088         
1089         strncpy(namebuf, name, sizeof(namebuf));
1090
1091         /* First check if this is already an address */
1092         if (inet_pton(AF_INET6, name, &in)) {
1093             h.h_name = namebuf;
1094             h.h_addrtype = AF_INET6;
1095             h.h_length = sizeof(in);
1096             h.h_addr_list = (char **) addr_list;
1097             return &h;
1098         }
1099
1100         for (;;) {
1101
1102                 i = dns_lookup(namebuf, T_AAAA, nameservers, nameserver, &packet, &a);
1103
1104                 if (i < 0)
1105                         return 0;
1106
1107                 strncpy(namebuf, a.dotted, sizeof(namebuf));
1108                 free(a.dotted);
1109
1110
1111                 if (a.atype == T_CNAME) {               /* CNAME */
1112                         DPRINTF("Got a CNAME in gethostbyname()\n");
1113                         i = decode_dotted(packet, a.rdoffset, namebuf, sizeof(namebuf));
1114                         free(packet);
1115
1116                         if (i < 0)
1117                                 return 0;
1118                         if (++nest > MAX_RECURSE)
1119                                 return 0;
1120                         continue;
1121                 } else if (a.atype == T_AAAA) { /* ADDRESS */
1122                         memcpy(&in, a.rdata, sizeof(in));
1123                         h.h_name = namebuf;
1124                         h.h_addrtype = AF_INET6;
1125                         h.h_length = sizeof(in);
1126                         h.h_addr_list = (char **) addr_list;
1127                         free(packet);
1128                         break;
1129                 } else {
1130                         free(packet);
1131                         return 0;
1132                 }
1133         }
1134
1135         return &h;
1136 #endif /* __UCLIBC_HAS_IPV6__ */
1137 }
1138 #endif
1139
1140 #ifdef L_getnetbyname
1141
1142 struct netent * getnetbyname(const char * name)
1143 {
1144         return NULL;
1145 }
1146 #endif
1147
1148
1149 #ifdef L_res_init
1150
1151 int res_init(void)
1152 {
1153         return(0);
1154 }
1155 #endif
1156
1157
1158 #ifdef L_res_query
1159
1160 #ifndef MIN
1161 #define MIN(x, y)       ((x) < (y) ? (x) : (y))
1162 #endif
1163
1164 int res_query(const char *dname, int class, int type,
1165               unsigned char *answer, int anslen)
1166 {
1167         unsigned char * packet = 0;
1168         struct resolv_answer a;
1169         int i;
1170
1171         open_nameservers();
1172         
1173         if (!dname || class != 1 /* CLASS_IN */)
1174                 return(-1);
1175                 
1176         memset((char *) &a, '\0', sizeof(a));
1177
1178         i = dns_lookup(dname, type, nameservers, nameserver, &packet, &a);
1179         
1180         if (i < 0)
1181                 return(-1);
1182                         
1183         free(a.dotted);
1184                 
1185         if (a.atype == type) { /* CNAME*/
1186                 if (anslen && answer)
1187                         memcpy(answer, a.rdata, MIN(anslen, a.rdlength));
1188                 if (packet)
1189                         free(packet);
1190                 return(MIN(anslen, a.rdlength));
1191         }
1192         if (packet)
1193                 free(packet);
1194         return 0;
1195 }
1196 #endif
1197
1198
1199 #ifdef L_gethostbyaddr
1200 struct hostent *gethostbyaddr (const void *addr, socklen_t len, int type)
1201 {
1202         static struct hostent h;
1203         static char namebuf[256];
1204         static struct in_addr in;
1205         static struct in_addr *addr_list[2];
1206 #ifdef __UCLIBC_HAS_IPV6__
1207     char *qp;
1208         static struct in6_addr  in6;
1209         static struct in6_addr  *addr_list6[2];
1210 #endif /* __UCLIBC_HAS_IPV6__ */
1211         struct hostent *hp;
1212         unsigned char *packet;
1213         struct resolv_answer a;
1214         int i;
1215         int nest = 0;
1216
1217         if (!addr)
1218                 return 0;
1219         
1220     switch (type) {
1221         case AF_INET:
1222                 if (len != sizeof(struct in_addr))
1223                         return 0;
1224                 break;
1225 #ifdef __UCLIBC_HAS_IPV6__
1226         case AF_INET6:
1227                 if (len != sizeof(struct in6_addr))
1228                         return 0;
1229                 break;
1230 #endif /* __UCLIBC_HAS_IPV6__ */
1231         default:
1232                 return 0;
1233         }
1234
1235         if ((hp = get_hosts_byaddr(addr, len, type))) /* do /etc/hosts first */
1236                 return(hp);
1237
1238         open_nameservers();
1239
1240         memset(&h, 0, sizeof(h));
1241
1242         if(type == AF_INET) {
1243                 unsigned char *tmp_addr = (unsigned char *)addr;
1244
1245                 memcpy(&in.s_addr, addr, len);
1246
1247                 addr_list[0] = &in;
1248
1249                 sprintf(namebuf, "%u.%u.%u.%u.in-addr.arpa",
1250                         tmp_addr[3], tmp_addr[2], tmp_addr[1], tmp_addr[0]);
1251 #ifdef __UCLIBC_HAS_IPV6__
1252         } else {
1253                 memcpy(&in6.s6_addr, addr, len);
1254
1255                 addr_list6[0] = &in6;
1256         qp = namebuf;
1257
1258                 for (i = len - 1; i >= 0; i--) {
1259                         qp += sprintf(qp, "%x.%x.", in6.s6_addr[i] & 0xf,
1260                                 (in6.s6_addr[i] >> 4) & 0xf);
1261         }
1262         strcpy(qp, "ip6.int");
1263 #endif /* __UCLIBC_HAS_IPV6__ */
1264         }
1265
1266         addr_list[1] = 0;
1267
1268         for (;;) {
1269
1270                 i = dns_lookup(namebuf, T_PTR, nameservers, nameserver, &packet, &a);
1271
1272                 if (i < 0)
1273                         return 0;
1274
1275                 strncpy(namebuf, a.dotted, sizeof(namebuf));
1276                 free(a.dotted);
1277
1278                 if (a.atype == T_CNAME) {               /* CNAME */
1279                         DPRINTF("Got a CNAME in gethostbyaddr()\n");
1280                         i = decode_dotted(packet, a.rdoffset, namebuf, sizeof(namebuf));
1281                         free(packet);
1282
1283                         if (i < 0)
1284                                 return 0;
1285                         if (++nest > MAX_RECURSE)
1286                                 return 0;
1287                         continue;
1288                 } else if (a.atype == T_PTR) {  /* ADDRESS */
1289                         i = decode_dotted(packet, a.rdoffset, namebuf, sizeof(namebuf));
1290                         free(packet);
1291
1292                         h.h_name = namebuf;
1293                         h.h_addrtype = type;
1294
1295                         if(type == AF_INET) {
1296                                 h.h_length = sizeof(in);
1297 #ifdef __UCLIBC_HAS_IPV6__
1298                         } else {
1299                                 h.h_length = sizeof(in6);
1300 #endif /* __UCLIBC_HAS_IPV6__ */
1301                 }
1302
1303                         h.h_addr_list = (char **) addr_list;
1304                         break;
1305                 } else {
1306                         free(packet);
1307                         return 0;
1308                 }
1309         }
1310
1311         return &h;
1312 }
1313 #endif
1314
1315
1316 #ifdef L_read_etc_hosts
1317
1318 struct hostent * read_etc_hosts(const char * name, int type, int ip)
1319 {
1320         static struct hostent   h;
1321         static struct in_addr   in;
1322         static struct in_addr   *addr_list[2];
1323 #ifdef __UCLIBC_HAS_IPV6__
1324         static struct in6_addr  in6;
1325         static struct in6_addr  *addr_list6[2];
1326 #endif /* __UCLIBC_HAS_IPV6__ */
1327         static char                             line[80];
1328         FILE                                    *fp;
1329         char                                    *cp;
1330 #define          MAX_ALIAS              5
1331         char                                    *alias[MAX_ALIAS];
1332         int                                             aliases, i;
1333
1334         if ((fp = fopen("/etc/hosts", "r")) == NULL &&
1335                         (fp = fopen("/etc/config/hosts", "r")) == NULL)
1336                 return((struct hostent *) NULL);
1337
1338         while (fgets(line, sizeof(line), fp)) {
1339                 if ((cp = strchr(line, '#')))
1340                         *cp = '\0';
1341                 aliases = 0;
1342
1343                 cp = line;
1344                 while (*cp) {
1345                         while (*cp && isspace(*cp))
1346                                 *cp++ = '\0';
1347                         if (!*cp)
1348                                 continue;
1349                         if (aliases < MAX_ALIAS)
1350                                 alias[aliases++] = cp;
1351                         while (*cp && !isspace(*cp))
1352                                 cp++;
1353                 }
1354
1355                 if (aliases < 2)
1356                         continue; /* syntax error really */
1357                 
1358                 if (ip) {
1359                         if (strcmp(name, alias[0]) != 0)
1360                                 continue;
1361                 } else {
1362                         for (i = 1; i < aliases; i++)
1363                                 if (strcasecmp(name, alias[i]) == 0)
1364                                         break;
1365                         if (i >= aliases)
1366                                 continue;
1367                 }
1368
1369                 if (type == AF_INET && inet_pton(AF_INET, alias[0], &in) > 0) {
1370                         addr_list[0] = &in;
1371                         addr_list[1] = 0;
1372                         h.h_name = alias[1];
1373                         h.h_addrtype = AF_INET;
1374                         h.h_length = sizeof(in);
1375                         h.h_addr_list = (char**) addr_list;
1376 #ifdef __UCLIBC_HAS_IPV6__
1377         } else if (type == AF_INET6 && inet_pton(AF_INET6, alias[0], &in6) > 0) {
1378                         addr_list6[0] = &in6;
1379                         addr_list6[1] = 0;
1380                         h.h_name = alias[1];
1381                         h.h_addrtype = AF_INET6;
1382                         h.h_length = sizeof(in6);
1383                         h.h_addr_list = (char**) addr_list6;
1384 #endif /* __UCLIBC_HAS_IPV6__ */
1385                 } else {
1386                         break; /* bad ip address */
1387         }
1388         
1389                 fclose(fp);
1390                 return(&h);
1391         }
1392         fclose(fp);
1393         return((struct hostent *) NULL);
1394 }
1395 #endif
1396
1397
1398 #ifdef L_get_hosts_byname
1399
1400 struct hostent * get_hosts_byname(const char * name, int type)
1401 {
1402         return(read_etc_hosts(name, type, 0));
1403 }
1404 #endif
1405
1406
1407 #ifdef L_get_hosts_byaddr
1408
1409 struct hostent * get_hosts_byaddr(const char * addr, int len, int type)
1410 {
1411 #ifndef __UCLIBC_HAS_IPV6__
1412         char    ipaddr[INET_ADDRSTRLEN];
1413 #else
1414         char    ipaddr[INET6_ADDRSTRLEN];
1415 #endif /* __UCLIBC_HAS_IPV6__ */
1416
1417     switch (type) {
1418         case AF_INET:
1419                 if (len != sizeof(struct in_addr))
1420                         return 0;
1421                 break;
1422 #ifdef __UCLIBC_HAS_IPV6__
1423         case AF_INET6:
1424                 if (len != sizeof(struct in6_addr))
1425                         return 0;
1426                 break;
1427 #endif /* __UCLIBC_HAS_IPV6__ */
1428         default:
1429                 return 0;
1430         }
1431
1432         inet_ntop(type, addr, ipaddr, sizeof(ipaddr));
1433
1434         return(read_etc_hosts(ipaddr, type, 1));
1435 }
1436 #endif
1437
1438 #ifdef L_getnameinfo
1439
1440 #ifndef min
1441 # define min(x,y) (((x) > (y)) ? (y) : (x))
1442 #endif /* min */
1443
1444 int getnameinfo (const struct sockaddr *sa, socklen_t addrlen, char *host,
1445              socklen_t hostlen, char *serv, socklen_t servlen,
1446              unsigned int flags)
1447 {
1448         int serrno = errno;
1449         int ok = 0;
1450         struct hostent *h = NULL;
1451     char domain[256];
1452     
1453         if (flags & ~(NI_NUMERICHOST|NI_NUMERICSERV|NI_NOFQDN|NI_NAMEREQD|NI_DGRAM))
1454                 return EAI_BADFLAGS;
1455
1456         if (sa == NULL || addrlen < sizeof (sa_family_t))
1457                 return EAI_FAMILY;
1458
1459         switch (sa->sa_family) {
1460         case AF_LOCAL:
1461                 break;
1462         case AF_INET:
1463                 if (addrlen < sizeof (struct sockaddr_in))
1464                         return EAI_FAMILY;
1465                 break;
1466 #ifdef __UCLIBC_HAS_IPV6__
1467         case AF_INET6:
1468                 if (addrlen < sizeof (struct sockaddr_in6))
1469                         return EAI_FAMILY;
1470                 break;
1471 #endif /* __UCLIBC_HAS_IPV6__ */
1472         default:
1473                 return EAI_FAMILY;
1474         }
1475
1476         if (host != NULL && hostlen > 0)
1477                 switch (sa->sa_family) {
1478                 case AF_INET:
1479 #ifdef __UCLIBC_HAS_IPV6__
1480                 case AF_INET6:
1481 #endif /* __UCLIBC_HAS_IPV6__ */
1482                         if (!(flags & NI_NUMERICHOST)) {
1483 #ifdef __UCLIBC_HAS_IPV6__
1484                                 if (sa->sa_family == AF_INET6)
1485                                         h = gethostbyaddr ((const void *) &(((const struct sockaddr_in6 *) sa)->sin6_addr),
1486                                                 sizeof(struct in6_addr), AF_INET6);
1487                                 else
1488 #endif /* __UCLIBC_HAS_IPV6__ */
1489                     h = gethostbyaddr ((const void *) &(((const struct sockaddr_in *)sa)->sin_addr),
1490                                           sizeof(struct in_addr), AF_INET);
1491
1492                                 if (h) {
1493                                         char *c;
1494                                         if ((flags & NI_NOFQDN)
1495                                             && (getdomainname (domain, sizeof(domain)) == 0)
1496                                             && (c = strstr (h->h_name, domain))
1497                                             && (c != h->h_name) && (*(--c) == '.')) {
1498                                                 strncpy (host, h->h_name,
1499                                                         min(hostlen, (size_t) (c - h->h_name)));
1500                                                 host[min(hostlen - 1, (size_t) (c - h->h_name))] = '\0';
1501                                                 ok = 1;
1502                                         } else {
1503                                                 strncpy (host, h->h_name, hostlen);
1504                                                 ok = 1;
1505                                         }
1506                                  }
1507                         }
1508
1509                         if (!ok) {
1510                                 if (flags & NI_NAMEREQD) {
1511                                         errno = serrno;
1512                                         return EAI_NONAME;
1513                                 } else {
1514                                         const char *c;
1515 #ifdef __UCLIBC_HAS_IPV6__
1516                                         if (sa->sa_family == AF_INET6) {
1517                                                 const struct sockaddr_in6 *sin6p;
1518
1519                                                 sin6p = (const struct sockaddr_in6 *) sa;
1520
1521                                                 c = inet_ntop (AF_INET6,
1522                                                         (const void *) &sin6p->sin6_addr, host, hostlen);
1523 #if 0
1524 /* Does scope id need to be supported? */
1525                                                 uint32_t scopeid;
1526                                                 scopeid = sin6p->sin6_scope_id;
1527                                                 if (scopeid != 0) {
1528                                                         /* Buffer is >= IFNAMSIZ+1.  */
1529                                                         char scopebuf[IFNAMSIZ + 1];
1530                                                         char *scopeptr;
1531                                                         int ni_numericscope = 0;
1532                                                         size_t real_hostlen = __strnlen (host, hostlen);
1533                                                         size_t scopelen = 0;
1534
1535                                                         scopebuf[0] = SCOPE_DELIMITER;
1536                                                         scopebuf[1] = '\0';
1537                                                         scopeptr = &scopebuf[1];
1538
1539                                                         if (IN6_IS_ADDR_LINKLOCAL (&sin6p->sin6_addr)
1540                                                             || IN6_IS_ADDR_MC_LINKLOCAL (&sin6p->sin6_addr)) {
1541                                                                 if (if_indextoname (scopeid, scopeptr) == NULL)
1542                                                                         ++ni_numericscope;
1543                                                                 else
1544                                                                         scopelen = strlen (scopebuf);
1545                                                         } else {
1546                                                                 ++ni_numericscope;
1547                             }
1548
1549                                                         if (ni_numericscope)
1550                                                                 scopelen = 1 + snprintf (scopeptr,
1551                                                                         (scopebuf
1552                                                                         + sizeof scopebuf
1553                                                                         - scopeptr),
1554                                                                         "%u", scopeid);
1555
1556                                                         if (real_hostlen + scopelen + 1 > hostlen)
1557                                                                 return EAI_SYSTEM;
1558                                                         memcpy (host + real_hostlen, scopebuf, scopelen + 1);
1559                                                 }
1560 #endif
1561                                         } else
1562 #endif /* __UCLIBC_HAS_IPV6__ */
1563                                                 c = inet_ntop (AF_INET,
1564                                                         (const void *) &(((const struct sockaddr_in *) sa)->sin_addr),
1565                                                         host, hostlen);
1566
1567                                         if (c == NULL) {
1568                                                 errno = serrno;
1569                                                 return EAI_SYSTEM;
1570                                         }
1571                                 }
1572                                 ok = 1;
1573                         }
1574                         break;
1575
1576                 case AF_LOCAL:
1577                         if (!(flags & NI_NUMERICHOST)) {
1578                                 struct utsname utsname;
1579
1580                                 if (!uname (&utsname)) {
1581                                         strncpy (host, utsname.nodename, hostlen);
1582                                         break;
1583                                 };
1584                         };
1585
1586                         if (flags & NI_NAMEREQD) {
1587                                 errno = serrno;
1588                                 return EAI_NONAME;
1589                         }
1590
1591                         strncpy (host, "localhost", hostlen);
1592                         break;
1593
1594                 default:
1595                         return EAI_FAMILY;
1596         }
1597
1598         if (serv && (servlen > 0)) {
1599                 switch (sa->sa_family) {
1600                 case AF_INET:
1601 #ifdef __UCLIBC_HAS_IPV6__
1602                 case AF_INET6:
1603 #endif /* __UCLIBC_HAS_IPV6__ */
1604                         if (!(flags & NI_NUMERICSERV)) {
1605                                 struct servent *s;
1606                                 s = getservbyport (((const struct sockaddr_in *) sa)->sin_port,
1607                                       ((flags & NI_DGRAM) ? "udp" : "tcp"));
1608                                 if (s) {
1609                                         strncpy (serv, s->s_name, servlen);
1610                                         break;
1611                                 }
1612                         }
1613                         snprintf (serv, servlen, "%d",
1614                                 ntohs (((const struct sockaddr_in *) sa)->sin_port));
1615                         break;
1616
1617                 case AF_LOCAL:
1618                         strncpy (serv, ((const struct sockaddr_un *) sa)->sun_path, servlen);
1619                         break;
1620                 }
1621         }
1622         if (host && (hostlen > 0))
1623                 host[hostlen-1] = 0;
1624         if (serv && (servlen > 0))
1625                 serv[servlen-1] = 0;
1626         errno = serrno;
1627         return 0;
1628 }
1629 #endif
This page took 0.120177 seconds and 4 git commands to generate.