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