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