chiark / gitweb /
WIP mostly works, need to convert if index to name
[adns.git] / client / addrtext.c
1 /*
2  * addrtext.c
3  * - test program for address<->string conversion, not part of the library
4  */
5 /*
6  *  This file is part of adns, which is
7  *    Copyright (C) 1997-2000,2003,2006,2014  Ian Jackson
8  *    Copyright (C) 1999-2000,2003,2006  Tony Finch
9  *    Copyright (C) 1991 Massachusetts Institute of Technology
10  *  (See the file INSTALL for full details.)
11  *  
12  *  This program is free software; you can redistribute it and/or modify
13  *  it under the terms of the GNU General Public License as published by
14  *  the Free Software Foundation; either version 2, or (at your option)
15  *  any later version.
16  *  
17  *  This program is distributed in the hope that it will be useful,
18  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  *  GNU General Public License for more details.
21  *  
22  *  You should have received a copy of the GNU General Public License
23  *  along with this program; if not, write to the Free Software Foundation,
24  *  Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
25  */
26
27 #include <sys/types.h>
28 #include <sys/socket.h>
29 #include <netdb.h>
30 #include <stdbool.h>
31 #include <string.h>
32 #include <errno.h>
33 #include <inttypes.h>
34
35 #include "config.h"
36 #include "adns.h"
37
38 #define PORT 1234
39
40 #define STRING(x) STRING2(x)
41 #define STRING2(x) #x
42
43 static int fails;
44
45 static void hex(const void *data_v, int l) {
46   const uint8_t *data= data_v;
47   int i;
48   for (i=0; i<l; i++)
49     printf("%02x",data[i]);
50 }
51
52 static void dump(const char *pfx, struct sockaddr *sa, socklen_t salen) {
53   int i;
54   printf(" %s: ",pfx);
55   hex(sa, salen);
56
57   for (i=0; i<salen; i++)
58     printf("%02x",((const uint8_t*)sa)[i]);
59
60   printf(" %d ", sa->sa_family);
61
62   switch (sa->sa_family) {
63   case AF_INET: {
64     const struct sockaddr_in *s = (const void*)sa;
65     printf(".port=%d .addr=%08"PRIx32"",
66            ntohs(s->sin_port),
67            (uint32_t)ntohl(s->sin_addr.s_addr));
68     break;
69   }
70   case AF_INET6: {
71     const struct sockaddr_in6 *s = (const void*)sa;
72     printf(".port=%d .flowinfo=%08"PRIx32" .scope_id=%08"PRIx32" .addr=",
73            ntohs(s->sin6_port),
74            (uint32_t)ntohl(s->sin6_flowinfo),
75            (uint32_t)ntohl(s->sin6_scope_id));
76     hex(&s->sin6_addr, sizeof(s->sin6_addr));
77     break;
78   }
79   }
80   printf("\n");
81 }
82
83 static void dotest(const char *input) {
84   adns_sockaddr ours;
85   socklen_t socklen;
86   struct addrinfo aip;
87   struct addrinfo *air=0;
88   char ourbuf[ADNS_ADDR2TEXT_BUFLEN];
89   char theirbuf[ADNS_ADDR2TEXT_BUFLEN];
90
91   memset(&ours,0,sizeof(ours));
92
93   socklen= sizeof(ours);
94   int our_r= adns_text2addr(input,PORT,&ours.sa,&socklen);
95
96   memset(&aip,0,sizeof(aip));
97   aip.ai_flags= AI_NUMERICHOST|AI_NUMERICSERV;
98   aip.ai_socktype= SOCK_DGRAM;
99   aip.ai_protocol= IPPROTO_UDP;
100   air= 0;
101   int libc_r= getaddrinfo(input,STRING(PORT),&aip,&air);
102   printf("`%s': us %s; libc %s, air=%p",
103          input, strerror(our_r), libc_r ? gai_strerror(libc_r) : "0", air);
104   if (air)
105     printf(" .family=%d .socklen=%ld .addr=%p .next=%p",
106            air->ai_family, (long)air->ai_addrlen, air->ai_addr, air->ai_next);
107   printf(":");
108
109   if (our_r==EINVAL && libc_r==EAI_NONAME && !air) {
110     printf(" invalid");
111     goto ok;
112   }
113   printf(" valid");
114
115 #define FAIL do{ printf(" | FAIL\n"); fails++; }while(0)
116 #define WANT(x) if (!(x)) { printf(" not %s",STRING(x)); FAIL; return; } else;
117
118   WANT(!our_r);
119   WANT(!libc_r);
120   WANT(air);
121   WANT(air->ai_addr);
122   WANT(!air->ai_next);
123   if (air->ai_addrlen!=socklen || memcmp(&ours,air->ai_addr,socklen)) {
124     printf(" mismatch");
125     FAIL;
126     dump("ours",&ours.sa,socklen);
127     dump("libc",air->ai_addr,air->ai_addrlen);
128     return;
129   }
130
131   printf(" |");
132
133   int ourbuflen= sizeof(ourbuf);
134   int ourport;
135   our_r= adns_addr2text(&ours.sa, ourbuf,&ourbuflen, &ourport);
136
137   printf(" us %s",strerror(our_r));
138   if (!our_r)
139     printf(" `%s'",ourbuf);
140
141   size_t theirbuflen= sizeof(theirbuf);
142   libc_r= getnameinfo(&ours.sa,socklen, theirbuf,theirbuflen, 0,0,
143                       NI_NUMERICHOST|NI_NUMERICSERV);
144   printf("; libc %s", libc_r ? gai_strerror(libc_r) : "0");
145   if (!libc_r)
146     printf(" `%s'",theirbuf);
147
148   printf(":");
149
150   WANT(!our_r);
151   WANT(!libc_r);
152   WANT(ourport==PORT);
153   if (strcmp(ourbuf,theirbuf)) {
154     printf(" mismatch");
155     FAIL;
156     return;
157   }
158
159  ok:
160   printf(" | PASS\n");
161 }
162
163 int main(int argc, char **argv) {
164   const char *arg;
165   while ((arg= *++argv)) {
166     dotest(arg);
167   }
168   return !!fails;
169 }