xref: /dragonfly/sys/netgraph/async/ng_async.c (revision 8a7bdfea)
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.7 2008/01/05 14:02:39 swildner 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 | M_ZERO);
187 	if (sc == NULL)
188 		return (ENOMEM);
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 {
237 	const sc_p sc = hook->node->private;
238 
239 	if (hook == sc->sync)
240 		return (nga_rcv_sync(sc, m, meta));
241 	if (hook == sc->async)
242 		return (nga_rcv_async(sc, m, meta));
243 	panic(__func__);
244 }
245 
246 /*
247  * Receive incoming control message
248  */
249 static int
250 nga_rcvmsg(node_p node, struct ng_mesg *msg,
251 	const char *rtn, struct ng_mesg **rptr)
252 {
253 	const sc_p sc = (sc_p) node->private;
254 	struct ng_mesg *resp = NULL;
255 	int error = 0;
256 
257 	switch (msg->header.typecookie) {
258 	case NGM_ASYNC_COOKIE:
259 		switch (msg->header.cmd) {
260 		case NGM_ASYNC_CMD_GET_STATS:
261 			NG_MKRESPONSE(resp, msg, sizeof(sc->stats), M_NOWAIT);
262 			if (resp == NULL)
263 				ERROUT(ENOMEM);
264 			*((struct ng_async_stat *) resp->data) = sc->stats;
265 			break;
266 		case NGM_ASYNC_CMD_CLR_STATS:
267 			bzero(&sc->stats, sizeof(sc->stats));
268 			break;
269 		case NGM_ASYNC_CMD_SET_CONFIG:
270 		    {
271 			struct ng_async_cfg *const cfg =
272 				(struct ng_async_cfg *) msg->data;
273 			u_char *buf;
274 
275 			if (msg->header.arglen != sizeof(*cfg))
276 				ERROUT(EINVAL);
277 			if (cfg->amru < NG_ASYNC_MIN_MRU
278 			    || cfg->amru > NG_ASYNC_MAX_MRU
279 			    || cfg->smru < NG_ASYNC_MIN_MRU
280 			    || cfg->smru > NG_ASYNC_MAX_MRU)
281 				ERROUT(EINVAL);
282 			cfg->enabled = !!cfg->enabled;	/* normalize */
283 			if (cfg->smru > sc->cfg.smru) {	/* reallocate buffer */
284 				MALLOC(buf, u_char *, ASYNC_BUF_SIZE(cfg->smru),
285 				    M_NETGRAPH, M_NOWAIT);
286 				if (!buf)
287 					ERROUT(ENOMEM);
288 				FREE(sc->abuf, M_NETGRAPH);
289 				sc->abuf = buf;
290 			}
291 			if (cfg->amru > sc->cfg.amru) {	/* reallocate buffer */
292 				MALLOC(buf, u_char *, SYNC_BUF_SIZE(cfg->amru),
293 				    M_NETGRAPH, M_NOWAIT);
294 				if (!buf)
295 					ERROUT(ENOMEM);
296 				FREE(sc->sbuf, M_NETGRAPH);
297 				sc->sbuf = buf;
298 				sc->amode = MODE_HUNT;
299 				sc->slen = 0;
300 			}
301 			if (!cfg->enabled) {
302 				sc->amode = MODE_HUNT;
303 				sc->slen = 0;
304 			}
305 			sc->cfg = *cfg;
306 			break;
307 		    }
308 		case NGM_ASYNC_CMD_GET_CONFIG:
309 			NG_MKRESPONSE(resp, msg, sizeof(sc->cfg), M_NOWAIT);
310 			if (!resp)
311 				ERROUT(ENOMEM);
312 			*((struct ng_async_cfg *) resp->data) = sc->cfg;
313 			break;
314 		default:
315 			ERROUT(EINVAL);
316 		}
317 		break;
318 	default:
319 		ERROUT(EINVAL);
320 	}
321 	if (rptr)
322 		*rptr = resp;
323 	else if (resp)
324 		FREE(resp, M_NETGRAPH);
325 
326 done:
327 	FREE(msg, M_NETGRAPH);
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 = node->private;
338 
339 	ng_cutlinks(node);
340 	ng_unname(node);
341 	FREE(sc->abuf, M_NETGRAPH);
342 	FREE(sc->sbuf, M_NETGRAPH);
343 	bzero(sc, sizeof(*sc));
344 	FREE(sc, M_NETGRAPH);
345 	node->private = NULL;
346 	ng_unref(node);
347 	return (0);
348 }
349 
350 /*
351  * Lose a hook. When both hooks go away, we disappear.
352  */
353 static int
354 nga_disconnect(hook_p hook)
355 {
356 	const sc_p sc = hook->node->private;
357 	hook_p *hookp;
358 
359 	if (hook == sc->async)
360 		hookp = &sc->async;
361 	else if (hook == sc->sync)
362 		hookp = &sc->sync;
363 	else
364 		panic(__func__);
365 	if (!*hookp)
366 		panic("%s2", __func__);
367 	*hookp = NULL;
368 	bzero(&sc->stats, sizeof(sc->stats));
369 	sc->lasttime = 0;
370 	if (hook->node->numhooks == 0)
371 		ng_rmnode(hook->node);
372 	return (0);
373 }
374 
375 /******************************************************************
376 		    INTERNAL HELPER STUFF
377 ******************************************************************/
378 
379 /*
380  * Encode a byte into the async buffer
381  */
382 static __inline__ void
383 nga_async_add(const sc_p sc, u_int16_t *fcs, u_int32_t accm, int *len, u_char x)
384 {
385 	*fcs = PPP_FCS(*fcs, x);
386 	if ((x < 32 && ((1 << x) & accm))
387 	    || (x == PPP_ESCAPE)
388 	    || (x == PPP_FLAG)) {
389 		sc->abuf[(*len)++] = PPP_ESCAPE;
390 		x ^= PPP_TRANS;
391 	}
392 	sc->abuf[(*len)++] = x;
393 }
394 
395 /*
396  * Receive incoming synchronous data.
397  */
398 static int
399 nga_rcv_sync(const sc_p sc, struct mbuf *m, meta_p meta)
400 {
401 	struct ifnet *const rcvif = m->m_pkthdr.rcvif;
402 	int alen, error = 0;
403 	struct timeval time;
404 	u_int16_t fcs, fcs0;
405 	u_int32_t accm;
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_SEND_DATA(error, sc->async, m, meta);
412 		return (error);
413 	}
414 
415 	/* Get ACCM; special case LCP frames, which use full ACCM */
416 	accm = sc->cfg.accm;
417 	if (m->m_pkthdr.len >= 4) {
418 		static const u_char lcphdr[4] = {
419 		    PPP_ALLSTATIONS,
420 		    PPP_UI,
421 		    (u_char)(PPP_LCP >> 8),
422 		    (u_char)(PPP_LCP & 0xff)
423 		};
424 		u_char buf[4];
425 
426 		m_copydata(m, 0, 4, (caddr_t)buf);
427 		if (bcmp(buf, &lcphdr, 4) == 0)
428 			accm = ~0;
429 	}
430 
431 	/* Check for overflow */
432 	if (m->m_pkthdr.len > sc->cfg.smru) {
433 		sc->stats.syncOverflows++;
434 		NG_FREE_DATA(m, meta);
435 		return (EMSGSIZE);
436 	}
437 
438 	/* Update stats */
439 	sc->stats.syncFrames++;
440 	sc->stats.syncOctets += m->m_pkthdr.len;
441 
442 	/* Initialize async encoded version of input mbuf */
443 	alen = 0;
444 	fcs = PPP_INITFCS;
445 
446 	/* Add beginning sync flag if it's been long enough to need one */
447 	getmicrotime(&time);
448 	if (time.tv_sec >= sc->lasttime + 1) {
449 		sc->abuf[alen++] = PPP_FLAG;
450 		sc->lasttime = time.tv_sec;
451 	}
452 
453 	/* Add packet payload */
454 	while (m != NULL) {
455 		while (m->m_len > 0) {
456 			ADD_BYTE(*mtod(m, u_char *));
457 			m->m_data++;
458 			m->m_len--;
459 		}
460 		m = m_free(m);
461 	}
462 
463 	/* Add checksum and final sync flag */
464 	fcs0 = fcs;
465 	ADD_BYTE(~fcs0 & 0xff);
466 	ADD_BYTE(~fcs0 >> 8);
467 	sc->abuf[alen++] = PPP_FLAG;
468 
469 	/* Put frame in an mbuf and ship it off */
470 	if (!(m = m_devget(sc->abuf, alen, 0, rcvif, NULL))) {
471 		NG_FREE_META(meta);
472 		error = ENOBUFS;
473 	} else
474 		NG_SEND_DATA(error, sc->async, m, meta);
475 	return (error);
476 }
477 
478 /*
479  * Receive incoming asynchronous data
480  * XXX Technically, we should strip out incoming characters
481  *     that are in our ACCM. Not sure if this is good or not.
482  */
483 static int
484 nga_rcv_async(const sc_p sc, struct mbuf * m, meta_p meta)
485 {
486 	struct ifnet *const rcvif = m->m_pkthdr.rcvif;
487 	int error;
488 
489 	if (!sc->cfg.enabled) {
490 		NG_SEND_DATA(error, sc->sync, m, meta);
491 		return (error);
492 	}
493 	NG_FREE_META(meta);
494 	while (m) {
495 		struct mbuf *n;
496 
497 		for (; m->m_len > 0; m->m_data++, m->m_len--) {
498 			u_char  ch = *mtod(m, u_char *);
499 
500 			sc->stats.asyncOctets++;
501 			if (ch == PPP_FLAG) {	/* Flag overrides everything */
502 				int     skip = 0;
503 
504 				/* Check for runts */
505 				if (sc->slen < 2) {
506 					if (sc->slen > 0)
507 						sc->stats.asyncRunts++;
508 					goto reset;
509 				}
510 
511 				/* Verify CRC */
512 				if (sc->fcs != PPP_GOODFCS) {
513 					sc->stats.asyncBadCheckSums++;
514 					goto reset;
515 				}
516 				sc->slen -= 2;
517 
518 				/* Strip address and control fields */
519 				if (sc->slen >= 2
520 				    && sc->sbuf[0] == PPP_ALLSTATIONS
521 				    && sc->sbuf[1] == PPP_UI)
522 					skip = 2;
523 
524 				/* Check for frame too big */
525 				if (sc->slen - skip > sc->cfg.amru) {
526 					sc->stats.asyncOverflows++;
527 					goto reset;
528 				}
529 
530 				/* OK, ship it out */
531 				if ((n = m_devget(sc->sbuf + skip,
532 					   sc->slen - skip, 0, rcvif, NULL)))
533 					NG_SEND_DATA(error, sc->sync, n, meta);
534 				sc->stats.asyncFrames++;
535 reset:
536 				sc->amode = MODE_NORMAL;
537 				sc->fcs = PPP_INITFCS;
538 				sc->slen = 0;
539 				continue;
540 			}
541 			switch (sc->amode) {
542 			case MODE_NORMAL:
543 				if (ch == PPP_ESCAPE) {
544 					sc->amode = MODE_ESC;
545 					continue;
546 				}
547 				break;
548 			case MODE_ESC:
549 				ch ^= PPP_TRANS;
550 				sc->amode = MODE_NORMAL;
551 				break;
552 			case MODE_HUNT:
553 			default:
554 				continue;
555 			}
556 
557 			/* Add byte to frame */
558 			if (sc->slen >= SYNC_BUF_SIZE(sc->cfg.amru)) {
559 				sc->stats.asyncOverflows++;
560 				sc->amode = MODE_HUNT;
561 				sc->slen = 0;
562 			} else {
563 				sc->sbuf[sc->slen++] = ch;
564 				sc->fcs = PPP_FCS(sc->fcs, ch);
565 			}
566 		}
567 		m = m_free(m);
568 	}
569 	return (0);
570 }
571 
572 /*
573  * CRC table
574  *
575  * Taken from RFC 1171 Appendix B
576  */
577 static const u_int16_t fcstab[256] = {
578 	 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
579 	 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
580 	 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
581 	 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
582 	 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
583 	 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
584 	 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
585 	 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
586 	 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
587 	 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
588 	 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
589 	 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
590 	 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
591 	 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
592 	 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
593 	 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
594 	 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
595 	 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
596 	 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
597 	 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
598 	 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
599 	 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
600 	 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
601 	 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
602 	 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
603 	 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
604 	 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
605 	 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
606 	 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
607 	 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
608 	 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
609 	 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
610 };
611