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