xref: /freebsd/sys/netgraph/ng_async.c (revision 27beb2e98db3193bd22010b9eb00cc7787bb0a2f)
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$
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 <netgraph/ng_async.h>
58 #include <netgraph/ng_parse.h>
59 
60 #include <net/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_info
102 	nga_config_type_info = NG_ASYNC_CONFIG_TYPE_INFO;
103 static const struct ng_parse_type nga_config_type = {
104 	&ng_parse_struct_type,
105 	&nga_config_type_info
106 };
107 
108 /* Parse type for struct ng_async_stat */
109 static const struct ng_parse_struct_info
110 	nga_stats_type_info = NG_ASYNC_STATS_TYPE_INFO;
111 static const struct ng_parse_type nga_stats_type = {
112 	&ng_parse_struct_type,
113 	&nga_stats_type_info,
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 	MALLOC(sc, sc_p, sizeof(*sc), M_NETGRAPH, M_NOWAIT);
186 	if (sc == NULL)
187 		return (ENOMEM);
188 	bzero(sc, sizeof(*sc));
189 	sc->amode = MODE_HUNT;
190 	sc->cfg.accm = ~0;
191 	sc->cfg.amru = NG_ASYNC_DEFAULT_MRU;
192 	sc->cfg.smru = NG_ASYNC_DEFAULT_MRU;
193 	MALLOC(sc->abuf, u_char *,
194 	    ASYNC_BUF_SIZE(sc->cfg.smru), M_NETGRAPH, M_NOWAIT);
195 	if (sc->abuf == NULL)
196 		goto fail;
197 	MALLOC(sc->sbuf, u_char *,
198 	    SYNC_BUF_SIZE(sc->cfg.amru), M_NETGRAPH, M_NOWAIT);
199 	if (sc->sbuf == NULL) {
200 		FREE(sc->abuf, M_NETGRAPH);
201 fail:
202 		FREE(sc, M_NETGRAPH);
203 		return (ENOMEM);
204 	}
205 	(*nodep)->private = sc;
206 	sc->node = *nodep;
207 	return (0);
208 }
209 
210 /*
211  * Reserve a hook for a pending connection
212  */
213 static int
214 nga_newhook(node_p node, hook_p hook, const char *name)
215 {
216 	const sc_p sc = node->private;
217 	hook_p *hookp;
218 
219 	if (!strcmp(name, NG_ASYNC_HOOK_ASYNC))
220 		hookp = &sc->async;
221 	else if (!strcmp(name, NG_ASYNC_HOOK_SYNC))
222 		hookp = &sc->sync;
223 	else
224 		return (EINVAL);
225 	if (*hookp)
226 		return (EISCONN);
227 	*hookp = hook;
228 	return (0);
229 }
230 
231 /*
232  * Receive incoming data
233  */
234 static int
235 nga_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
236 		struct mbuf **ret_m, meta_p *ret_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, hook_p lasthook)
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(__FUNCTION__ "2");
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 		struct mbuf *n;
457 
458 		while (m->m_len > 0) {
459 			ADD_BYTE(*mtod(m, u_char *));
460 			m->m_data++;
461 			m->m_len--;
462 		}
463 		MFREE(m, n);
464 		m = n;
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_META(meta);
476 		error = ENOBUFS;
477 	} else
478 		NG_SEND_DATA(error, sc->async, m, meta);
479 	return (error);
480 }
481 
482 /*
483  * Receive incoming asynchronous data
484  * XXX Technically, we should strip out incoming characters
485  *     that are in our ACCM. Not sure if this is good or not.
486  */
487 static int
488 nga_rcv_async(const sc_p sc, struct mbuf * m, meta_p meta)
489 {
490 	struct ifnet *const rcvif = m->m_pkthdr.rcvif;
491 	int error;
492 
493 	if (!sc->cfg.enabled) {
494 		NG_SEND_DATA(error, sc->sync, m, meta);
495 		return (error);
496 	}
497 	NG_FREE_META(meta);
498 	while (m) {
499 		struct mbuf *n;
500 
501 		for (; m->m_len > 0; m->m_data++, m->m_len--) {
502 			u_char  ch = *mtod(m, u_char *);
503 
504 			sc->stats.asyncOctets++;
505 			if (ch == PPP_FLAG) {	/* Flag overrides everything */
506 				int     skip = 0;
507 
508 				/* Check for runts */
509 				if (sc->slen < 2) {
510 					if (sc->slen > 0)
511 						sc->stats.asyncRunts++;
512 					goto reset;
513 				}
514 
515 				/* Verify CRC */
516 				if (sc->fcs != PPP_GOODFCS) {
517 					sc->stats.asyncBadCheckSums++;
518 					goto reset;
519 				}
520 				sc->slen -= 2;
521 
522 				/* Strip address and control fields */
523 				if (sc->slen >= 2
524 				    && sc->sbuf[0] == PPP_ALLSTATIONS
525 				    && sc->sbuf[1] == PPP_UI)
526 					skip = 2;
527 
528 				/* Check for frame too big */
529 				if (sc->slen - skip > sc->cfg.amru) {
530 					sc->stats.asyncOverflows++;
531 					goto reset;
532 				}
533 
534 				/* OK, ship it out */
535 				if ((n = m_devget(sc->sbuf + skip,
536 					   sc->slen - skip, 0, rcvif, NULL)))
537 					NG_SEND_DATA(error, sc->sync, n, meta);
538 				sc->stats.asyncFrames++;
539 reset:
540 				sc->amode = MODE_NORMAL;
541 				sc->fcs = PPP_INITFCS;
542 				sc->slen = 0;
543 				continue;
544 			}
545 			switch (sc->amode) {
546 			case MODE_NORMAL:
547 				if (ch == PPP_ESCAPE) {
548 					sc->amode = MODE_ESC;
549 					continue;
550 				}
551 				break;
552 			case MODE_ESC:
553 				ch ^= PPP_TRANS;
554 				sc->amode = MODE_NORMAL;
555 				break;
556 			case MODE_HUNT:
557 			default:
558 				continue;
559 			}
560 
561 			/* Add byte to frame */
562 			if (sc->slen >= SYNC_BUF_SIZE(sc->cfg.amru)) {
563 				sc->stats.asyncOverflows++;
564 				sc->amode = MODE_HUNT;
565 				sc->slen = 0;
566 			} else {
567 				sc->sbuf[sc->slen++] = ch;
568 				sc->fcs = PPP_FCS(sc->fcs, ch);
569 			}
570 		}
571 		MFREE(m, n);
572 		m = n;
573 	}
574 	return (0);
575 }
576 
577 /*
578  * CRC table
579  *
580  * Taken from RFC 1171 Appendix B
581  */
582 static const u_int16_t fcstab[256] = {
583 	 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
584 	 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
585 	 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
586 	 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
587 	 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
588 	 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
589 	 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
590 	 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
591 	 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
592 	 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
593 	 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
594 	 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
595 	 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
596 	 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
597 	 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
598 	 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
599 	 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
600 	 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
601 	 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
602 	 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
603 	 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
604 	 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
605 	 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
606 	 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
607 	 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
608 	 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
609 	 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
610 	 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
611 	 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
612 	 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
613 	 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
614 	 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
615 };
616