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