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