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