Merge branch 'vendor/TCPDUMP' (early part)
[dragonfly.git] / sys / netgraph / async / ng_async.c
1
2 /*
3  * ng_async.c
4  *
5  * Copyright (c) 1996-1999 Whistle Communications, Inc.
6  * All rights reserved.
7  * 
8  * Subject to the following obligations and disclaimer of warranty, use and
9  * redistribution of this software, in source or object code forms, with or
10  * without modifications are expressly permitted by Whistle Communications;
11  * provided, however, that:
12  * 1. Any and all reproductions of the source or object code must include the
13  *    copyright notice above and the following disclaimer of warranties; and
14  * 2. No rights are granted, in any manner or form, to use Whistle
15  *    Communications, Inc. trademarks, including the mark "WHISTLE
16  *    COMMUNICATIONS" on advertising, endorsements, or otherwise except as
17  *    such appears in the above copyright notice or in the software.
18  * 
19  * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
20  * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
21  * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
22  * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
23  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
24  * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
25  * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
26  * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
27  * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
28  * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
29  * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
30  * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
31  * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
32  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34  * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
35  * OF SUCH DAMAGE.
36  *
37  * Author: Archie Cobbs <archie@freebsd.org>
38  *
39  * $FreeBSD: src/sys/netgraph/ng_async.c,v 1.6.2.5 2002/07/02 23:44:02 archie Exp $
40  * $DragonFly: src/sys/netgraph/async/ng_async.c,v 1.7 2008/01/05 14:02:39 swildner Exp $
41  * $Whistle: ng_async.c,v 1.17 1999/11/01 09:24:51 julian Exp $
42  */
43
44 /*
45  * This node type implements a PPP style sync <-> async converter.
46  * See RFC 1661 for details of how asynchronous encoding works.
47  */
48
49 #include <sys/param.h>
50 #include <sys/systm.h>
51 #include <sys/kernel.h>
52 #include <sys/mbuf.h>
53 #include <sys/malloc.h>
54 #include <sys/errno.h>
55
56 #include <netgraph/ng_message.h>
57 #include <netgraph/netgraph.h>
58 #include "ng_async.h"
59 #include <netgraph/ng_parse.h>
60
61 #include <net/ppp_layer/ppp_defs.h>
62
63 /* Async decode state */
64 #define MODE_HUNT       0
65 #define MODE_NORMAL     1
66 #define MODE_ESC        2
67
68 /* Private data structure */
69 struct ng_async_private {
70         node_p          node;           /* Our node */
71         hook_p          async;          /* Asynchronous side */
72         hook_p          sync;           /* Synchronous side */
73         u_char          amode;          /* Async hunt/esape mode */
74         u_int16_t       fcs;            /* Decoded async FCS (so far) */
75         u_char         *abuf;           /* Buffer to encode sync into */
76         u_char         *sbuf;           /* Buffer to decode async into */
77         u_int           slen;           /* Length of data in sbuf */
78         long            lasttime;       /* Time of last async packet sent */
79         struct          ng_async_cfg    cfg;    /* Configuration */
80         struct          ng_async_stat   stats;  /* Statistics */
81 };
82 typedef struct ng_async_private *sc_p;
83
84 /* Useful macros */
85 #define ASYNC_BUF_SIZE(smru)    (2 * (smru) + 10)
86 #define SYNC_BUF_SIZE(amru)     ((amru) + 10)
87 #define ERROUT(x)               do { error = (x); goto done; } while (0)
88
89 /* Netgraph methods */
90 static ng_constructor_t         nga_constructor;
91 static ng_rcvdata_t             nga_rcvdata;
92 static ng_rcvmsg_t              nga_rcvmsg;
93 static ng_shutdown_t            nga_shutdown;
94 static ng_newhook_t             nga_newhook;
95 static ng_disconnect_t          nga_disconnect;
96
97 /* Helper stuff */
98 static int      nga_rcv_sync(const sc_p sc, struct mbuf *m, meta_p meta);
99 static int      nga_rcv_async(const sc_p sc, struct mbuf *m, meta_p meta);
100
101 /* Parse type for struct ng_async_cfg */
102 static const struct ng_parse_struct_field nga_config_type_fields[]
103         = NG_ASYNC_CONFIG_TYPE_INFO;
104 static const struct ng_parse_type nga_config_type = {
105         &ng_parse_struct_type,
106         &nga_config_type_fields
107 };
108
109 /* Parse type for struct ng_async_stat */
110 static const struct ng_parse_struct_field nga_stats_type_fields[]
111         = NG_ASYNC_STATS_TYPE_INFO;
112 static const struct ng_parse_type nga_stats_type = {
113         &ng_parse_struct_type,
114         &nga_stats_type_fields
115 };
116
117 /* List of commands and how to convert arguments to/from ASCII */
118 static const struct ng_cmdlist nga_cmdlist[] = {
119         {
120           NGM_ASYNC_COOKIE,
121           NGM_ASYNC_CMD_SET_CONFIG,
122           "setconfig",
123           &nga_config_type,
124           NULL
125         },
126         {
127           NGM_ASYNC_COOKIE,
128           NGM_ASYNC_CMD_GET_CONFIG,
129           "getconfig",
130           NULL,
131           &nga_config_type
132         },
133         {
134           NGM_ASYNC_COOKIE,
135           NGM_ASYNC_CMD_GET_STATS,
136           "getstats",
137           NULL,
138           &nga_stats_type
139         },
140         {
141           NGM_ASYNC_COOKIE,
142           NGM_ASYNC_CMD_CLR_STATS,
143           "clrstats",
144           &nga_stats_type,
145           NULL
146         },
147         { 0 }
148 };
149
150 /* Define the netgraph node type */
151 static struct ng_type typestruct = {
152         NG_VERSION,
153         NG_ASYNC_NODE_TYPE,
154         NULL,
155         nga_constructor,
156         nga_rcvmsg,
157         nga_shutdown,
158         nga_newhook,
159         NULL,
160         NULL,
161         nga_rcvdata,
162         nga_rcvdata,
163         nga_disconnect,
164         nga_cmdlist
165 };
166 NETGRAPH_INIT(async, &typestruct);
167
168 /* CRC table */
169 static const u_int16_t fcstab[];
170
171 /******************************************************************
172                     NETGRAPH NODE METHODS
173 ******************************************************************/
174
175 /*
176  * Initialize a new node
177  */
178 static int
179 nga_constructor(node_p *nodep)
180 {
181         sc_p sc;
182         int error;
183
184         if ((error = ng_make_node_common(&typestruct, nodep)))
185                 return (error);
186         MALLOC(sc, sc_p, sizeof(*sc), M_NETGRAPH, M_NOWAIT | M_ZERO);
187         if (sc == NULL)
188                 return (ENOMEM);
189         sc->amode = MODE_HUNT;
190         sc->cfg.accm = ~0;
191         sc->cfg.amru = NG_ASYNC_DEFAULT_MRU;
192         sc->cfg.smru = NG_ASYNC_DEFAULT_MRU;
193         MALLOC(sc->abuf, u_char *,
194             ASYNC_BUF_SIZE(sc->cfg.smru), M_NETGRAPH, M_NOWAIT);
195         if (sc->abuf == NULL)
196                 goto fail;
197         MALLOC(sc->sbuf, u_char *,
198             SYNC_BUF_SIZE(sc->cfg.amru), M_NETGRAPH, M_NOWAIT);
199         if (sc->sbuf == NULL) {
200                 FREE(sc->abuf, M_NETGRAPH);
201 fail:
202                 FREE(sc, M_NETGRAPH);
203                 return (ENOMEM);
204         }
205         (*nodep)->private = sc;
206         sc->node = *nodep;
207         return (0);
208 }
209
210 /*
211  * Reserve a hook for a pending connection
212  */
213 static int
214 nga_newhook(node_p node, hook_p hook, const char *name)
215 {
216         const sc_p sc = node->private;
217         hook_p *hookp;
218
219         if (!strcmp(name, NG_ASYNC_HOOK_ASYNC))
220                 hookp = &sc->async;
221         else if (!strcmp(name, NG_ASYNC_HOOK_SYNC))
222                 hookp = &sc->sync;
223         else
224                 return (EINVAL);
225         if (*hookp)
226                 return (EISCONN);
227         *hookp = hook;
228         return (0);
229 }
230
231 /*
232  * Receive incoming data
233  */
234 static int
235 nga_rcvdata(hook_p hook, struct mbuf *m, meta_p meta)
236 {
237         const sc_p sc = hook->node->private;
238
239         if (hook == sc->sync)
240                 return (nga_rcv_sync(sc, m, meta));
241         if (hook == sc->async)
242                 return (nga_rcv_async(sc, m, meta));
243         panic(__func__);
244 }
245
246 /*
247  * Receive incoming control message
248  */
249 static int
250 nga_rcvmsg(node_p node, struct ng_mesg *msg,
251         const char *rtn, struct ng_mesg **rptr)
252 {
253         const sc_p sc = (sc_p) node->private;
254         struct ng_mesg *resp = NULL;
255         int error = 0;
256
257         switch (msg->header.typecookie) {
258         case NGM_ASYNC_COOKIE:
259                 switch (msg->header.cmd) {
260                 case NGM_ASYNC_CMD_GET_STATS:
261                         NG_MKRESPONSE(resp, msg, sizeof(sc->stats), M_NOWAIT);
262                         if (resp == NULL)
263                                 ERROUT(ENOMEM);
264                         *((struct ng_async_stat *) resp->data) = sc->stats;
265                         break;
266                 case NGM_ASYNC_CMD_CLR_STATS:
267                         bzero(&sc->stats, sizeof(sc->stats));
268                         break;
269                 case NGM_ASYNC_CMD_SET_CONFIG:
270                     {
271                         struct ng_async_cfg *const cfg =
272                                 (struct ng_async_cfg *) msg->data;
273                         u_char *buf;
274
275                         if (msg->header.arglen != sizeof(*cfg))
276                                 ERROUT(EINVAL);
277                         if (cfg->amru < NG_ASYNC_MIN_MRU
278                             || cfg->amru > NG_ASYNC_MAX_MRU
279                             || cfg->smru < NG_ASYNC_MIN_MRU
280                             || cfg->smru > NG_ASYNC_MAX_MRU)
281                                 ERROUT(EINVAL);
282                         cfg->enabled = !!cfg->enabled;  /* normalize */
283                         if (cfg->smru > sc->cfg.smru) { /* reallocate buffer */
284                                 MALLOC(buf, u_char *, ASYNC_BUF_SIZE(cfg->smru),
285                                     M_NETGRAPH, M_NOWAIT);
286                                 if (!buf)
287                                         ERROUT(ENOMEM);
288                                 FREE(sc->abuf, M_NETGRAPH);
289                                 sc->abuf = buf;
290                         }
291                         if (cfg->amru > sc->cfg.amru) { /* reallocate buffer */
292                                 MALLOC(buf, u_char *, SYNC_BUF_SIZE(cfg->amru),
293                                     M_NETGRAPH, M_NOWAIT);
294                                 if (!buf)
295                                         ERROUT(ENOMEM);
296                                 FREE(sc->sbuf, M_NETGRAPH);
297                                 sc->sbuf = buf;
298                                 sc->amode = MODE_HUNT;
299                                 sc->slen = 0;
300                         }
301                         if (!cfg->enabled) {
302                                 sc->amode = MODE_HUNT;
303                                 sc->slen = 0;
304                         }
305                         sc->cfg = *cfg;
306                         break;
307                     }
308                 case NGM_ASYNC_CMD_GET_CONFIG:
309                         NG_MKRESPONSE(resp, msg, sizeof(sc->cfg), M_NOWAIT);
310                         if (!resp)
311                                 ERROUT(ENOMEM);
312                         *((struct ng_async_cfg *) resp->data) = sc->cfg;
313                         break;
314                 default:
315                         ERROUT(EINVAL);
316                 }
317                 break;
318         default:
319                 ERROUT(EINVAL);
320         }
321         if (rptr)
322                 *rptr = resp;
323         else if (resp)
324                 FREE(resp, M_NETGRAPH);
325
326 done:
327         FREE(msg, M_NETGRAPH);
328         return (error);
329 }
330
331 /*
332  * Shutdown this node
333  */
334 static int
335 nga_shutdown(node_p node)
336 {
337         const sc_p sc = node->private;
338
339         ng_cutlinks(node);
340         ng_unname(node);
341         FREE(sc->abuf, M_NETGRAPH);
342         FREE(sc->sbuf, M_NETGRAPH);
343         bzero(sc, sizeof(*sc));
344         FREE(sc, M_NETGRAPH);
345         node->private = NULL;
346         ng_unref(node);
347         return (0);
348 }
349
350 /*
351  * Lose a hook. When both hooks go away, we disappear.
352  */
353 static int
354 nga_disconnect(hook_p hook)
355 {
356         const sc_p sc = hook->node->private;
357         hook_p *hookp;
358
359         if (hook == sc->async)
360                 hookp = &sc->async;
361         else if (hook == sc->sync)
362                 hookp = &sc->sync;
363         else
364                 panic(__func__);
365         if (!*hookp)
366                 panic("%s2", __func__);
367         *hookp = NULL;
368         bzero(&sc->stats, sizeof(sc->stats));
369         sc->lasttime = 0;
370         if (hook->node->numhooks == 0)
371                 ng_rmnode(hook->node);
372         return (0);
373 }
374
375 /******************************************************************
376                     INTERNAL HELPER STUFF
377 ******************************************************************/
378
379 /*
380  * Encode a byte into the async buffer
381  */
382 static __inline__ void
383 nga_async_add(const sc_p sc, u_int16_t *fcs, u_int32_t accm, int *len, u_char x)
384 {
385         *fcs = PPP_FCS(*fcs, x);
386         if ((x < 32 && ((1 << x) & accm))
387             || (x == PPP_ESCAPE)
388             || (x == PPP_FLAG)) {
389                 sc->abuf[(*len)++] = PPP_ESCAPE;
390                 x ^= PPP_TRANS;
391         }
392         sc->abuf[(*len)++] = x;
393 }
394
395 /*
396  * Receive incoming synchronous data.
397  */
398 static int
399 nga_rcv_sync(const sc_p sc, struct mbuf *m, meta_p meta)
400 {
401         struct ifnet *const rcvif = m->m_pkthdr.rcvif;
402         int alen, error = 0;
403         struct timeval time;
404         u_int16_t fcs, fcs0;
405         u_int32_t accm;
406
407 #define ADD_BYTE(x)     nga_async_add(sc, &fcs, accm, &alen, (x))
408
409         /* Check for bypass mode */
410         if (!sc->cfg.enabled) {
411                 NG_SEND_DATA(error, sc->async, m, meta);
412                 return (error);
413         }
414
415         /* Get ACCM; special case LCP frames, which use full ACCM */
416         accm = sc->cfg.accm;
417         if (m->m_pkthdr.len >= 4) {
418                 static const u_char lcphdr[4] = {
419                     PPP_ALLSTATIONS,
420                     PPP_UI,
421                     (u_char)(PPP_LCP >> 8),
422                     (u_char)(PPP_LCP & 0xff)
423                 };
424                 u_char buf[4];
425
426                 m_copydata(m, 0, 4, (caddr_t)buf);
427                 if (bcmp(buf, &lcphdr, 4) == 0)
428                         accm = ~0;
429         }
430
431         /* Check for overflow */
432         if (m->m_pkthdr.len > sc->cfg.smru) {
433                 sc->stats.syncOverflows++;
434                 NG_FREE_DATA(m, meta);
435                 return (EMSGSIZE);
436         }
437
438         /* Update stats */
439         sc->stats.syncFrames++;
440         sc->stats.syncOctets += m->m_pkthdr.len;
441
442         /* Initialize async encoded version of input mbuf */
443         alen = 0;
444         fcs = PPP_INITFCS;
445
446         /* Add beginning sync flag if it's been long enough to need one */
447         getmicrotime(&time);
448         if (time.tv_sec >= sc->lasttime + 1) {
449                 sc->abuf[alen++] = PPP_FLAG;
450                 sc->lasttime = time.tv_sec;
451         }
452
453         /* Add packet payload */
454         while (m != NULL) {
455                 while (m->m_len > 0) {
456                         ADD_BYTE(*mtod(m, u_char *));
457                         m->m_data++;
458                         m->m_len--;
459                 }
460                 m = m_free(m);
461         }
462
463         /* Add checksum and final sync flag */
464         fcs0 = fcs;
465         ADD_BYTE(~fcs0 & 0xff);
466         ADD_BYTE(~fcs0 >> 8);
467         sc->abuf[alen++] = PPP_FLAG;
468
469         /* Put frame in an mbuf and ship it off */
470         if (!(m = m_devget(sc->abuf, alen, 0, rcvif, NULL))) {
471                 NG_FREE_META(meta);
472                 error = ENOBUFS;
473         } else
474                 NG_SEND_DATA(error, sc->async, m, meta);
475         return (error);
476 }
477
478 /*
479  * Receive incoming asynchronous data
480  * XXX Technically, we should strip out incoming characters
481  *     that are in our ACCM. Not sure if this is good or not.
482  */
483 static int
484 nga_rcv_async(const sc_p sc, struct mbuf * m, meta_p meta)
485 {
486         struct ifnet *const rcvif = m->m_pkthdr.rcvif;
487         int error;
488
489         if (!sc->cfg.enabled) {
490                 NG_SEND_DATA(error, sc->sync, m, meta);
491                 return (error);
492         }
493         NG_FREE_META(meta);
494         while (m) {
495                 struct mbuf *n;
496
497                 for (; m->m_len > 0; m->m_data++, m->m_len--) {
498                         u_char  ch = *mtod(m, u_char *);
499
500                         sc->stats.asyncOctets++;
501                         if (ch == PPP_FLAG) {   /* Flag overrides everything */
502                                 int     skip = 0;
503
504                                 /* Check for runts */
505                                 if (sc->slen < 2) {
506                                         if (sc->slen > 0)
507                                                 sc->stats.asyncRunts++;
508                                         goto reset;
509                                 }
510
511                                 /* Verify CRC */
512                                 if (sc->fcs != PPP_GOODFCS) {
513                                         sc->stats.asyncBadCheckSums++;
514                                         goto reset;
515                                 }
516                                 sc->slen -= 2;
517
518                                 /* Strip address and control fields */
519                                 if (sc->slen >= 2
520                                     && sc->sbuf[0] == PPP_ALLSTATIONS
521                                     && sc->sbuf[1] == PPP_UI)
522                                         skip = 2;
523
524                                 /* Check for frame too big */
525                                 if (sc->slen - skip > sc->cfg.amru) {
526                                         sc->stats.asyncOverflows++;
527                                         goto reset;
528                                 }
529
530                                 /* OK, ship it out */
531                                 if ((n = m_devget(sc->sbuf + skip,
532                                            sc->slen - skip, 0, rcvif, NULL)))
533                                         NG_SEND_DATA(error, sc->sync, n, meta);
534                                 sc->stats.asyncFrames++;
535 reset:
536                                 sc->amode = MODE_NORMAL;
537                                 sc->fcs = PPP_INITFCS;
538                                 sc->slen = 0;
539                                 continue;
540                         }
541                         switch (sc->amode) {
542                         case MODE_NORMAL:
543                                 if (ch == PPP_ESCAPE) {
544                                         sc->amode = MODE_ESC;
545                                         continue;
546                                 }
547                                 break;
548                         case MODE_ESC:
549                                 ch ^= PPP_TRANS;
550                                 sc->amode = MODE_NORMAL;
551                                 break;
552                         case MODE_HUNT:
553                         default:
554                                 continue;
555                         }
556
557                         /* Add byte to frame */
558                         if (sc->slen >= SYNC_BUF_SIZE(sc->cfg.amru)) {
559                                 sc->stats.asyncOverflows++;
560                                 sc->amode = MODE_HUNT;
561                                 sc->slen = 0;
562                         } else {
563                                 sc->sbuf[sc->slen++] = ch;
564                                 sc->fcs = PPP_FCS(sc->fcs, ch);
565                         }
566                 }
567                 m = m_free(m);
568         }
569         return (0);
570 }
571
572 /*
573  * CRC table
574  *
575  * Taken from RFC 1171 Appendix B
576  */
577 static const u_int16_t fcstab[256] = {
578          0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
579          0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
580          0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
581          0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
582          0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
583          0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
584          0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
585          0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
586          0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
587          0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
588          0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
589          0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
590          0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
591          0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
592          0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
593          0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
594          0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
595          0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
596          0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
597          0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
598          0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
599          0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
600          0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
601          0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
602          0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
603          0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
604          0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
605          0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
606          0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
607          0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
608          0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
609          0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
610 };