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