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