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