]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/ntp/libparse/clk_hopf6021.c
Fix multiple vulnerabilities of ntp.
[FreeBSD/releng/10.2.git] / contrib / ntp / libparse / clk_hopf6021.c
1 /*
2  * /src/NTP/ntp4-dev/libparse/clk_hopf6021.c,v 4.10 2004/11/14 15:29:41 kardel RELEASE_20050508_A
3  *
4  * clk_hopf6021.c,v 4.10 2004/11/14 15:29:41 kardel RELEASE_20050508_A
5  *
6  * Radiocode Clocks HOPF Funkuhr 6021 mit serieller Schnittstelle
7  * base code version from 24th Nov 1995 - history at end
8  *
9  * Created by F.Schnekenbuehl <frank@comsys.dofn.de> from clk_rcc8000.c
10  * Nortel DASA Network Systems GmbH, Department: ND250
11  * A Joint venture of Daimler-Benz Aerospace and Nortel
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16  *
17  */
18
19 #ifdef HAVE_CONFIG_H
20 # include <config.h>
21 #endif
22
23 #if defined(REFCLOCK) && defined(CLOCK_PARSE) && defined(CLOCK_HOPF6021)
24
25 #include "ntp_fp.h"
26 #include "ntp_unixtime.h"
27 #include "ntp_calendar.h"
28 #include "ascii.h"
29
30 #include "parse.h"
31
32 #ifndef PARSESTREAM
33 #include "ntp_stdlib.h"
34 #include <stdio.h>
35 #else
36 #include "sys/parsestreams.h"
37 extern int printf (const char *, ...);
38 #endif
39
40 /*
41  * hopf Funkuhr 6021
42  *      used with 9600,8N1,
43  *      UTC ueber serielle Schnittstelle
44  *      Sekundenvorlauf ON
45  *      ETX zum Sekundenvorlauf ON
46  *      Datenstring 6021
47  *      Ausgabe Uhrzeit und Datum
48  *      Senden mit Steuerzeichen
49  *      Senden sekuendlich
50  */
51
52 /*
53  *  Type 6021 Serial Output format
54  *
55  *      000000000011111111 / char
56  *      012345678901234567 \ position
57  *      sABHHMMSSDDMMYYnre  Actual
58  *       C4110046231195     Parse
59  *      s              enr  Check
60  *
61  *  s = STX (0x02), e = ETX (0x03)
62  *  n = NL  (0x0A), r = CR  (0x0D)
63  *
64  *  A B - Status and weekday
65  *
66  *  A - Status
67  *
68  *      8 4 2 1
69  *      x x x 0  - no announcement
70  *      x x x 1  - Summertime - wintertime - summertime announcement
71  *      x x 0 x  - Wintertime
72  *      x x 1 x  - Summertime
73  *      0 0 x x  - Time/Date invalid
74  *      0 1 x x  - Internal clock used
75  *      1 0 x x  - Radio clock
76  *      1 1 x x  - Radio clock highprecision
77  *
78  *  B - 8 4 2 1
79  *      0 x x x  - MESZ/MEZ
80  *      1 x x x  - UTC
81  *      x 0 0 1  - Monday
82  *      x 0 1 0  - Tuesday
83  *      x 0 1 1  - Wednesday
84  *      x 1 0 0  - Thursday
85  *      x 1 0 1  - Friday
86  *      x 1 1 0  - Saturday
87  *      x 1 1 1  - Sunday
88  */
89
90 #define HOPF_DSTWARN    0x01    /* DST switch warning */
91 #define HOPF_DST        0x02    /* DST in effect */
92
93 #define HOPF_MODE       0x0C    /* operation mode mask */
94 #define  HOPF_INVALID   0x00    /* no time code available */
95 #define  HOPF_INTERNAL  0x04    /* internal clock */
96 #define  HOPF_RADIO     0x08    /* radio clock */
97 #define  HOPF_RADIOHP   0x0C    /* high precision radio clock */
98
99 #define HOPF_UTC        0x08    /* time code in UTC */
100 #define HOPF_WMASK      0x07    /* mask for weekday code */
101
102 static struct format hopf6021_fmt =
103 {
104         {
105                 {  9, 2 }, {11, 2}, { 13, 2}, /* Day, Month, Year */
106                 {  3, 2 }, { 5, 2}, {  7, 2}, /* Hour, Minute, Second */
107                 {  2, 1 }, { 1, 1}, {  0, 0}, /* Weekday, Flags, Zone */
108                 /* ... */
109         },
110         (const unsigned char *)"\002              \n\r\003",
111         0
112 };
113
114 #define OFFS(x) format->field_offsets[(x)].offset
115 #define STOI(x, y) Stoi(&buffer[OFFS(x)], y, format->field_offsets[(x)].length)
116
117 static parse_cvt_fnc_t cvt_hopf6021;
118 static parse_inp_fnc_t inp_hopf6021;
119 static unsigned char   hexval(unsigned char);
120
121 clockformat_t clock_hopf6021 =
122 {
123   inp_hopf6021,                 /* HOPF 6021 input handling */
124   cvt_hopf6021,                 /* Radiocode clock conversion */
125   0,                            /* no direct PPS monitoring */
126   (void *)&hopf6021_fmt,        /* conversion configuration */
127   "hopf Funkuhr 6021",          /* clock format name */
128   19,                           /* string buffer */
129   0                            /* private data length, no private data */
130 };
131
132 /* parse_cvt_fnc_t cvt_hopf6021 */
133 static u_long
134 cvt_hopf6021(
135              unsigned char *buffer,
136              int            size,
137              struct format *format,
138              clocktime_t   *clock_time,
139              void          *local
140              )
141 {
142         unsigned char status,weekday;
143
144         if (!Strok(buffer, format->fixed_string))
145         {
146                 return CVT_NONE;
147         }
148
149         if (  STOI(O_DAY,   &clock_time->day)    ||
150               STOI(O_MONTH, &clock_time->month)  ||
151               STOI(O_YEAR,  &clock_time->year)   ||
152               STOI(O_HOUR,  &clock_time->hour)   ||
153               STOI(O_MIN,   &clock_time->minute) ||
154               STOI(O_SEC,   &clock_time->second)
155               )
156         {
157                 return CVT_FAIL|CVT_BADFMT;
158         }
159
160         clock_time->usecond = 0;
161         clock_time->flags   = 0;
162
163         status  = hexval(buffer[OFFS(O_FLAGS)]);
164         weekday = hexval(buffer[OFFS(O_WDAY)]);
165
166         if ((status == 0xFF) || (weekday == 0xFF))
167         {
168                 return CVT_FAIL|CVT_BADFMT;
169         }
170
171         if (weekday & HOPF_UTC)
172         {
173                 clock_time->flags     |= PARSEB_UTC;
174                 clock_time->utcoffset  = 0;
175         }
176         else if (status & HOPF_DST)
177         {
178                 clock_time->flags     |= PARSEB_DST;
179                 clock_time->utcoffset  = -2*60*60; /* MET DST */
180         }
181         else
182         {
183                 clock_time->utcoffset  = -1*60*60; /* MET */
184         }
185
186         if (status & HOPF_DSTWARN)
187         {
188                 clock_time->flags |= PARSEB_ANNOUNCE;
189         }
190         
191         switch (status & HOPF_MODE)
192         {
193             default:    /* dummy: we cover all 4 cases. */
194             case HOPF_INVALID:  /* Time/Date invalid */
195                 clock_time->flags |= PARSEB_POWERUP;
196                 break;
197
198             case HOPF_INTERNAL: /* internal clock */
199                 clock_time->flags |= PARSEB_NOSYNC;
200                 break;
201
202             case HOPF_RADIO:    /* Radio clock */
203             case HOPF_RADIOHP:  /* Radio clock high precision */
204                 break;
205         }
206
207         return CVT_OK;
208 }
209
210 /*
211  * parse_inp_fnc_t inp_hopf6021
212  *
213  * grab data from input stream
214  */
215 static u_long
216 inp_hopf6021(
217              parse_t      *parseio,
218              char         ch,
219              timestamp_t  *tstamp
220           )
221 {
222         unsigned int rtc;
223
224         parseprintf(DD_PARSE, ("inp_hopf6021(0x%p, 0x%x, ...)\n", (void*)parseio, ch));
225
226         switch (ch)
227         {
228         case ETX:
229                 parseprintf(DD_PARSE, ("inp_hopf6021: EOL seen\n"));
230                 parseio->parse_dtime.parse_stime = *tstamp; /* collect timestamp */
231                 if ((rtc = parse_addchar(parseio, ch)) == PARSE_INP_SKIP)
232                         return parse_end(parseio);
233                 else
234                         return rtc;
235
236         default:
237                 return parse_addchar(parseio, ch);
238         }
239 }
240
241 /*
242  * convert a hex-digit to numeric value
243  */
244 static unsigned char
245 hexval(
246         unsigned char ch
247         )
248 {
249         unsigned int dv;
250         
251         if ((dv = ch - '0') >= 10u)
252         {
253                 if ((dv -= 'A'-'0') < 6u || (dv -= 'a'-'A') < 6u)
254                 {
255                         dv += 10;
256                 }
257                 else
258                 {
259                         dv = 0xFF;
260                 }
261         }
262         return (unsigned char)dv;
263 }
264
265 #else /* not (REFCLOCK && CLOCK_PARSE && CLOCK_HOPF6021) */
266 int clk_hopf6021_bs;
267 #endif /* not (REFCLOCK && CLOCK_PARSE && CLOCK_HOPF6021) */
268
269 /*
270  * History:
271  *
272  * clk_hopf6021.c,v
273  * Revision 4.10  2004/11/14 15:29:41  kardel
274  * support PPSAPI, upgrade Copyright to Berkeley style
275  *
276  * Revision 4.7  1999/11/28 09:13:49  kardel
277  * RECON_4_0_98F
278  *
279  * Revision 4.6  1998/11/15 20:27:57  kardel
280  * Release 4.0.73e13 reconcilation
281  *
282  * Revision 4.5  1998/06/14 21:09:35  kardel
283  * Sun acc cleanup
284  *
285  * Revision 4.4  1998/06/13 12:02:38  kardel
286  * fix SYSV clock name clash
287  *
288  * Revision 4.3  1998/06/12 15:22:27  kardel
289  * fix prototypes
290  *
291  * Revision 4.2  1998/06/12 09:13:25  kardel
292  * conditional compile macros fixed
293  * printf prototype
294  *
295  * Revision 4.1  1998/05/24 09:39:52  kardel
296  * implementation of the new IO handling model
297  *
298  * Revision 4.0  1998/04/10 19:45:29  kardel
299  * Start 4.0 release version numbering
300  *
301  * from V3 3.6 log info deleted 1998/04/11 kardel
302  */