4 * Copyright (C) 2006 Matthew Kehrer
5 * Copyright (C) 2006 Hans Leidekker
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "wine/debug.h"
24 #include "wine/unicode.h"
27 #include <sys/types.h>
29 #ifdef HAVE_NETINET_IN_H
30 # include <netinet/in.h>
32 #ifdef HAVE_ARPA_NAMESER_H
33 # include <arpa/nameser.h>
47 WINE_DEFAULT_DEBUG_CHANNEL(dnsapi
);
49 /******************************************************************************
50 * DnsNameCompare_A [DNSAPI.@]
53 BOOL WINAPI
DnsNameCompare_A( LPSTR name1
, LPSTR name2
)
56 LPWSTR name1W
, name2W
;
58 TRACE( "(%s,%s)\n", debugstr_a(name1
), debugstr_a(name2
) );
60 name1W
= dns_strdup_aw( name1
);
61 name2W
= dns_strdup_aw( name2
);
63 ret
= DnsNameCompare_W( name1W
, name2W
);
71 /******************************************************************************
72 * DnsNameCompare_W [DNSAPI.@]
75 BOOL WINAPI
DnsNameCompare_W( LPWSTR name1
, LPWSTR name2
)
79 TRACE( "(%s,%s)\n", debugstr_w(name1
), debugstr_w(name2
) );
81 if (!name1
&& !name2
) return TRUE
;
82 if (!name1
|| !name2
) return FALSE
;
84 p
= name1
+ lstrlenW( name1
) - 1;
85 q
= name2
+ lstrlenW( name2
) - 1;
87 while (*p
== '.' && p
>= name1
) p
--;
88 while (*q
== '.' && q
>= name2
) q
--;
90 if (p
- name1
!= q
- name2
) return FALSE
;
94 if (toupperW( *name1
) != toupperW( *name2
))
103 /******************************************************************************
104 * DnsValidateName_A [DNSAPI.@]
107 DNS_STATUS WINAPI
DnsValidateName_A( LPCSTR name
, DNS_NAME_FORMAT format
)
112 TRACE( "(%s, %d)\n", debugstr_a(name
), format
);
114 nameW
= dns_strdup_aw( name
);
115 ret
= DnsValidateName_W( nameW
, format
);
121 /******************************************************************************
122 * DnsValidateName_UTF8 [DNSAPI.@]
125 DNS_STATUS WINAPI
DnsValidateName_UTF8( LPCSTR name
, DNS_NAME_FORMAT format
)
130 TRACE( "(%s, %d)\n", debugstr_a(name
), format
);
132 nameW
= dns_strdup_uw( name
);
133 ret
= DnsValidateName_W( nameW
, format
);
139 #define HAS_EXTENDED 0x0001
140 #define HAS_NUMERIC 0x0002
141 #define HAS_NON_NUMERIC 0x0004
142 #define HAS_DOT 0x0008
143 #define HAS_DOT_DOT 0x0010
144 #define HAS_SPACE 0x0020
145 #define HAS_INVALID 0x0040
146 #define HAS_ASTERISK 0x0080
147 #define HAS_UNDERSCORE 0x0100
148 #define HAS_LONG_LABEL 0x0200
150 /******************************************************************************
151 * DnsValidateName_W [DNSAPI.@]
154 DNS_STATUS WINAPI
DnsValidateName_W( LPCWSTR name
, DNS_NAME_FORMAT format
)
157 unsigned int i
, j
, state
= 0;
158 static const WCHAR invalid
[] = {
159 '{','|','}','~','[','\\',']','^','\'',':',';','<','=','>',
160 '?','@','!','\"','#','$','%','^','`','(',')','+','/',',',0 };
162 TRACE( "(%s, %d)\n", debugstr_w(name
), format
);
164 if (!name
) return ERROR_INVALID_NAME
;
166 for (p
= name
, i
= 0, j
= 0; *p
; p
++, i
++, j
++)
172 if (p
[1] == '.') state
|= HAS_DOT_DOT
;
174 else if (*p
< '0' || *p
> '9') state
|= HAS_NON_NUMERIC
;
175 else state
|= HAS_NUMERIC
;
177 if (j
> 62) state
|= HAS_LONG_LABEL
;
179 if (strchrW( invalid
, *p
)) state
|= HAS_INVALID
;
180 else if ((unsigned)*p
> 127) state
|= HAS_EXTENDED
;
181 else if (*p
== ' ') state
|= HAS_SPACE
;
182 else if (*p
== '_') state
|= HAS_UNDERSCORE
;
183 else if (*p
== '*') state
|= HAS_ASTERISK
;
186 if (i
== 0 || i
> 255 ||
187 (state
& HAS_LONG_LABEL
) ||
188 (state
& HAS_DOT_DOT
) ||
189 (name
[0] == '.' && name
[1])) return ERROR_INVALID_NAME
;
195 if (!(state
& HAS_NON_NUMERIC
) && (state
& HAS_NUMERIC
))
196 return DNS_ERROR_NUMERIC_NAME
;
197 if ((state
& HAS_EXTENDED
) || (state
& HAS_UNDERSCORE
))
198 return DNS_ERROR_NON_RFC_NAME
;
199 if ((state
& HAS_SPACE
) ||
200 (state
& HAS_INVALID
) ||
201 (state
& HAS_ASTERISK
)) return DNS_ERROR_INVALID_NAME_CHAR
;
204 case DnsNameDomainLabel
:
206 if (state
& HAS_DOT
) return ERROR_INVALID_NAME
;
207 if ((state
& HAS_EXTENDED
) || (state
& HAS_UNDERSCORE
))
208 return DNS_ERROR_NON_RFC_NAME
;
209 if ((state
& HAS_SPACE
) ||
210 (state
& HAS_INVALID
) ||
211 (state
& HAS_ASTERISK
)) return DNS_ERROR_INVALID_NAME_CHAR
;
214 case DnsNameHostnameFull
:
216 if (!(state
& HAS_NON_NUMERIC
) && (state
& HAS_NUMERIC
))
217 return DNS_ERROR_NUMERIC_NAME
;
218 if ((state
& HAS_EXTENDED
) || (state
& HAS_UNDERSCORE
))
219 return DNS_ERROR_NON_RFC_NAME
;
220 if ((state
& HAS_SPACE
) ||
221 (state
& HAS_INVALID
) ||
222 (state
& HAS_ASTERISK
)) return DNS_ERROR_INVALID_NAME_CHAR
;
225 case DnsNameHostnameLabel
:
227 if (state
& HAS_DOT
) return ERROR_INVALID_NAME
;
228 if (!(state
& HAS_NON_NUMERIC
) && (state
& HAS_NUMERIC
))
229 return DNS_ERROR_NUMERIC_NAME
;
230 if ((state
& HAS_EXTENDED
) || (state
& HAS_UNDERSCORE
))
231 return DNS_ERROR_NON_RFC_NAME
;
232 if ((state
& HAS_SPACE
) ||
233 (state
& HAS_INVALID
) ||
234 (state
& HAS_ASTERISK
)) return DNS_ERROR_INVALID_NAME_CHAR
;
237 case DnsNameWildcard
:
239 if (!(state
& HAS_NON_NUMERIC
) && (state
& HAS_NUMERIC
))
240 return ERROR_INVALID_NAME
;
241 if (name
[0] != '*') return ERROR_INVALID_NAME
;
242 if (name
[1] && name
[1] != '.')
243 return DNS_ERROR_INVALID_NAME_CHAR
;
244 if ((state
& HAS_EXTENDED
) ||
245 (state
& HAS_SPACE
) ||
246 (state
& HAS_INVALID
)) return ERROR_INVALID_NAME
;
249 case DnsNameSrvRecord
:
251 if (!(state
& HAS_NON_NUMERIC
) && (state
& HAS_NUMERIC
))
252 return ERROR_INVALID_NAME
;
253 if (name
[0] != '_') return ERROR_INVALID_NAME
;
254 if ((state
& HAS_UNDERSCORE
) && !name
[1])
255 return DNS_ERROR_NON_RFC_NAME
;
256 if ((state
& HAS_EXTENDED
) ||
257 (state
& HAS_SPACE
) ||
258 (state
& HAS_INVALID
)) return ERROR_INVALID_NAME
;
262 WARN( "unknown format: %d\n", format
);
265 return ERROR_SUCCESS
;