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