Watt-32 tcp/ip  2.2 dev-rel.10
res_loc.c
Go to the documentation of this file.
1 
5 /* ++Copyright++ 1985, 1989, 1993
6  * -
7  * Copyright (c) 1985, 1989, 1993
8  * The Regents of the University of California. All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in the
17  * documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  * must display the following acknowledgement:
20  * This product includes software developed by the University of
21  * California, Berkeley and its contributors.
22  * 4. Neither the name of the University nor the names of its contributors
23  * may be used to endorse or promote products derived from this software
24  * without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  * -
38  * Portions Copyright (c) 1993 by Digital Equipment Corporation.
39  *
40  * Permission to use, copy, modify, and distribute this software for any
41  * purpose with or without fee is hereby granted, provided that the above
42  * copyright notice and this permission notice appear in all copies, and that
43  * the name of Digital Equipment Corporation not be used in advertising or
44  * publicity pertaining to distribution of the document or software without
45  * specific, written prior permission.
46  *
47  * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
48  * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
49  * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
50  * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
51  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
52  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
53  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
54  * SOFTWARE.
55  * -
56  * --Copyright--
57  *
58  * Code taken from RFC-1876
59  *
60  * Routines to convert between on-the-wire RR format and zone file
61  * format. Does not contain conversion to/from decimal degrees;
62  * divide or multiply by 60*60*1000 for that.
63  *
64  * Adapted for Watt-32 by Gisle Vanem 1997
65  */
66 
67 #include "resolver.h"
68 
69 #if defined(USE_BIND)
70 
71 static unsigned long power_of_ten[10] = {
72  1, 10, 100, 1000, 10000, 100000,
73  1000000,10000000,100000000,1000000000
74  };
75 
76 /*
77  * takes an XeY precision/size value, returns a string representation.
78  */
79 static const char *precsize_ntoa (BYTE prec)
80 {
81  static char retbuf[sizeof("90000000.00")];
82 
83  int mantissa = (int)((prec >> 4) & 0x0f) % 10;
84  int exponent = (int)((prec >> 0) & 0x0f) % 10;
85  DWORD value = mantissa * power_of_ten[exponent];
86 
87  sprintf (retbuf, "%lu.%.2lu", value / 100, value % 100);
88  return (retbuf);
89 }
90 
91 /*
92  * converts ASCII size/precision X * 10**Y(cm) to 0xXY. moves pointer.
93  */
94 static BYTE precsize_aton (char **strptr)
95 {
96  UINT mval = 0;
97  UINT cmval = 0;
98  BYTE retval = 0;
99  char *cp = *strptr;
100  int exponent;
101  int mantissa;
102 
103  while (isdigit((int)*cp))
104  mval = mval * 10 + (*cp++ - '0');
105 
106  if (*cp == '.') /* centimeters */
107  {
108  cp++;
109  if (isdigit((int)*cp))
110  {
111  cmval = (*cp++ - '0') * 10;
112  if (isdigit((int)*cp))
113  cmval += (*cp++ - '0');
114  }
115  }
116  cmval = (mval * 100) + cmval;
117 
118  for (exponent = 0; exponent < 9; exponent++)
119  if (cmval < power_of_ten[exponent+1])
120  break;
121 
122  mantissa = cmval / power_of_ten[exponent];
123  if (mantissa > 9)
124  mantissa = 9;
125 
126  retval = (mantissa << 4) | exponent;
127  *strptr = cp;
128  return (retval);
129 }
130 
131 /*
132  * Converts ASCII lat/long to unsigned encoded 32-bit number
133  */
134 static DWORD latlon2ul (char **latlonstrptr, int *which)
135 {
136  DWORD retval;
137  char *cp = *latlonstrptr;
138  int deg = 0;
139  int min = 0;
140  int secs = 0;
141  int secsfrac = 0;
142 
143  while (isdigit((int)*cp))
144  deg = deg * 10 + (*cp++ - '0');
145 
146  while (isspace((int)*cp))
147  cp++;
148 
149  if (!(isdigit((int)*cp)))
150  goto fndhemi;
151 
152  while (isdigit((int)*cp))
153  min = min * 10 + (*cp++ - '0');
154 
155  while (isspace((int)*cp))
156  cp++;
157 
158  if (!(isdigit((int)*cp)))
159  goto fndhemi;
160 
161  while (isdigit((int)*cp))
162  secs = secs * 10 + (*cp++ - '0');
163 
164  if (*cp == '.') /* decimal seconds */
165  {
166  cp++;
167  if (isdigit((int)*cp))
168  {
169  secsfrac = (*cp++ - '0') * 100;
170  if (isdigit((int)*cp))
171  {
172  secsfrac += (*cp++ - '0') * 10;
173  if (isdigit((int)*cp))
174  secsfrac += (*cp++ - '0');
175  }
176  }
177  }
178 
179  while (!isspace((int)*cp)) /* if any trailing garbage */
180  cp++;
181 
182  while (isspace((int)*cp))
183  cp++;
184 
185 fndhemi:
186 
187  switch (toupper((int)*cp))
188  {
189  case 'N':
190  case 'E':
191  retval = (1UL << 31UL)
192  + (((((deg * 60UL) + min) * 60UL) + secs) * 1000UL)
193  + secsfrac;
194  break;
195  case 'S':
196  case 'W':
197  retval = (1UL << 31UL)
198  - (((((deg * 60UL) + min) * 60UL) + secs) * 1000UL)
199  - secsfrac;
200  break;
201  default:
202  retval = 0; /* invalid value -- indicates error */
203  break;
204  }
205 
206  switch (toupper((int)*cp))
207  {
208  case 'N':
209  case 'S':
210  *which = 1; /* latitude */
211  break;
212  case 'E':
213  case 'W':
214  *which = 2; /* longitude */
215  break;
216  default:
217  *which = 0; /* error */
218  break;
219  }
220 
221  cp++; /* skip the hemisphere */
222 
223  while (!isspace((int)*cp)) /* if any trailing garbage */
224  cp++;
225 
226  while (isspace((int)*cp)) /* move to next field */
227  cp++;
228 
229  *latlonstrptr = cp;
230  return (retval);
231 }
232 
233 /*
234  * Converts a zone file representation in a string to an RDATA
235  * on-the-wire representation.
236  */
237 int W32_CALL loc_aton (const char *ascii, u_char *binary)
238 {
239  char *cp, *maxcp;
240  BYTE *bcp;
241  DWORD latit = 0, longit = 0, alt = 0;
242  DWORD lltemp1 = 0, lltemp2 = 0;
243  int altmeters = 0;
244  int altfrac = 0;
245  int altsign = 1;
246  BYTE hp = 0x16; /* default = 1E6 cm = 10000.00m = 10km */
247  BYTE vp = 0x13; /* default = 1E3 cm = 10.00m */
248  BYTE siz = 0x12; /* default = 1E2 cm = 1.00m */
249  int which1 = 0;
250  int which2 = 0;
251 
252  cp = (char*)ascii;
253  maxcp = cp + strlen (ascii);
254 
255  lltemp1 = latlon2ul (&cp, &which1);
256  lltemp2 = latlon2ul (&cp, &which2);
257 
258  switch (which1 + which2)
259  {
260  case 3: /* 1 + 2, the only valid combination */
261  if (which1 == 1 && which2 == 2) /* normal case */
262  {
263  latit = lltemp1;
264  longit = lltemp2;
265  }
266  else if (which1 == 2 && which2 == 1) /* reversed */
267  {
268  longit = lltemp1;
269  latit = lltemp2;
270  }
271  else /* some kind of brokenness */
272  return (0);
273  break;
274  default: /* we didn't get one of each */
275  return (0);
276  }
277 
278  /* altitude */
279  if (*cp == '-')
280  {
281  altsign = -1;
282  cp++;
283  }
284 
285  if (*cp == '+')
286  ++cp;
287 
288  while (isdigit((int)*cp))
289  altmeters = altmeters * 10 + (*cp++ - '0');
290 
291  if (*cp == '.') /* decimal meters */
292  {
293  cp++;
294  if (isdigit((int)*cp))
295  {
296  altfrac = (*cp++ - '0') * 10;
297  if (isdigit((int)*cp))
298  altfrac += (*cp++ - '0');
299  }
300  }
301 
302  alt = (10000000 + (altsign * (altmeters * 100 + altfrac)));
303 
304  while (!isspace((int)*cp) && (cp < maxcp))
305  cp++; /* if trailing garbage or m */
306 
307  while (isspace((int)*cp) && (cp < maxcp))
308  cp++;
309 
310  if (cp >= maxcp)
311  goto defaults;
312 
313  siz = precsize_aton (&cp);
314 
315  while (!isspace((int)*cp) && (cp < maxcp)) /* if trailing garbage or m */
316  cp++;
317 
318  while (isspace((int)*cp) && (cp < maxcp))
319  cp++;
320 
321  if (cp >= maxcp)
322  goto defaults;
323 
324  hp = precsize_aton (&cp);
325 
326  while (!isspace((int)*cp) && (cp < maxcp)) /* if trailing garbage or m */
327  cp++;
328 
329  while (isspace((int)*cp) && (cp < maxcp))
330  cp++;
331 
332  if (cp >= maxcp)
333  goto defaults;
334 
335  vp = precsize_aton (&cp);
336 
337  defaults:
338 
339  bcp = binary;
340  *bcp++ = (BYTE) 0; /* version byte */
341  *bcp++ = siz;
342  *bcp++ = hp;
343  *bcp++ = vp;
344  PUTLONG (latit, bcp);
345  PUTLONG (longit, bcp);
346  PUTLONG (alt, bcp);
347 
348  return (16); /* size of RR in octets */
349 }
350 
351 /*
352  * Takes an on-the-wire LOC RR and prints it in zone file
353  * (human readable) format.
354  */
355 char * W32_CALL loc_ntoa (const u_char *binary, char *ascii)
356 {
357  static char tmpbuf[255*3];
358  const DWORD referencealt = 100000UL * 100UL;
359  const BYTE *rcp;
360  char *cp0, *cp;
361 
362  int latdeg, latmin, latsec, latsecfrac;
363  int longdeg, longmin, longsec, longsecfrac;
364  char northsouth, eastwest;
365  int altmeters, altfrac, altsign;
366 
367  long latval, longval, altval;
368  DWORD templ;
369  BYTE sizeval, hpval, vpval, versionval;
370 
371  rcp = binary;
372  if (ascii)
373  cp0 = cp = ascii;
374  else cp0 = cp = tmpbuf;
375 
376  versionval = *rcp++;
377 
378  if (versionval)
379  {
380  sprintf (cp, "; error: unknown LOC RR version");
381  return (cp);
382  }
383 
384  sizeval = *rcp++;
385  hpval = *rcp++;
386  vpval = *rcp++;
387 
388  GETLONG (templ, rcp);
389  latval = (templ - (1UL << 31));
390 
391  GETLONG (templ, rcp);
392  longval = (templ - (1UL << 31));
393 
394  GETLONG (templ, rcp);
395  if (templ < referencealt) /* below WGS 84 spheroid */
396  {
397  altval = referencealt - templ;
398  altsign = -1;
399  }
400  else
401  {
402  altval = templ - referencealt;
403  altsign = 1;
404  }
405 
406  if (latval < 0)
407  {
408  northsouth = 'S';
409  latval = -latval;
410  }
411  else
412  northsouth = 'N';
413 
414  latsecfrac = latval % 1000;
415  latval = latval / 1000;
416  latsec = latval % 60;
417  latval = latval / 60;
418  latmin = latval % 60;
419  latval = latval / 60;
420  latdeg = latval;
421 
422  if (longval < 0)
423  {
424  eastwest = 'W';
425  longval = -longval;
426  }
427  else
428  eastwest = 'E';
429 
430  longsecfrac = longval % 1000;
431  longval = longval / 1000;
432  longsec = longval % 60;
433  longval = longval / 60;
434  longmin = longval % 60;
435  longval = longval / 60;
436  longdeg = longval;
437 
438  altfrac = altval % 100;
439  altmeters = (altval / 100) * altsign;
440 
441  cp += sprintf (cp,
442  "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %d.%.2dm",
443  latdeg, latmin, latsec, latsecfrac, northsouth,
444  longdeg, longmin, longsec, longsecfrac, eastwest,
445  altmeters, altfrac);
446 
447  cp += sprintf (cp, " %sm", precsize_ntoa(sizeval));
448  cp += sprintf (cp, " %sm", precsize_ntoa(hpval));
449  cp += sprintf (cp, " %sm", precsize_ntoa(vpval));
450 
451  return (cp0);
452 }
453 #endif /* USE_BIND */
454