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