1/*
2 * ng_async.c
3 */
4
5/*-
6 * Copyright (c) 1996-1999 Whistle Communications, Inc.
7 * All rights reserved.
8 *
9 * Subject to the following obligations and disclaimer of warranty, use and
10 * redistribution of this software, in source or object code forms, with or
11 * without modifications are expressly permitted by Whistle Communications;
12 * provided, however, that:
13 * 1. Any and all reproductions of the source or object code must include the
14 *    copyright notice above and the following disclaimer of warranties; and
15 * 2. No rights are granted, in any manner or form, to use Whistle
16 *    Communications, Inc. trademarks, including the mark "WHISTLE
17 *    COMMUNICATIONS" on advertising, endorsements, or otherwise except as
18 *    such appears in the above copyright notice or in the software.
19 *
20 * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
21 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
22 * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
23 * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
24 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
25 * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
26 * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
27 * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
28 * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
29 * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
30 * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
31 * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
32 * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35 * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
36 * OF SUCH DAMAGE.
37 *
38 * Author: Archie Cobbs <archie@freebsd.org>
39 *
40 * $FreeBSD$
41 * $Whistle: ng_async.c,v 1.17 1999/11/01 09:24:51 julian Exp $
42 */
43
44/*
45 * This node type implements a PPP style sync <-> async converter.
46 * See RFC 1661 for details of how asynchronous encoding works.
47 */
48
49#include <sys/param.h>
50#include <sys/systm.h>
51#include <sys/kernel.h>
52#include <sys/mbuf.h>
53#include <sys/malloc.h>
54#include <sys/errno.h>
55
56#include <netgraph/ng_message.h>
57#include <netgraph/netgraph.h>
58#include <netgraph/ng_async.h>
59#include <netgraph/ng_parse.h>
60
61#include <net/ppp_defs.h>
62
63#ifdef NG_SEPARATE_MALLOC
64static MALLOC_DEFINE(M_NETGRAPH_ASYNC, "netgraph_async", "netgraph async node");
65#else
66#define M_NETGRAPH_ASYNC M_NETGRAPH
67#endif
68
69
70/* Async decode state */
71#define MODE_HUNT	0
72#define MODE_NORMAL	1
73#define MODE_ESC	2
74
75/* Private data structure */
76struct ng_async_private {
77	node_p  	node;		/* Our node */
78	hook_p  	async;		/* Asynchronous side */
79	hook_p  	sync;		/* Synchronous side */
80	u_char  	amode;		/* Async hunt/esape mode */
81	u_int16_t	fcs;		/* Decoded async FCS (so far) */
82	u_char	       *abuf;		/* Buffer to encode sync into */
83	u_char	       *sbuf;		/* Buffer to decode async into */
84	u_int		slen;		/* Length of data in sbuf */
85	long		lasttime;	/* Time of last async packet sent */
86	struct		ng_async_cfg	cfg;	/* Configuration */
87	struct		ng_async_stat	stats;	/* Statistics */
88};
89typedef struct ng_async_private *sc_p;
90
91/* Useful macros */
92#define ASYNC_BUF_SIZE(smru)	(2 * (smru) + 10)
93#define SYNC_BUF_SIZE(amru)	((amru) + 10)
94#define ERROUT(x)		do { error = (x); goto done; } while (0)
95
96/* Netgraph methods */
97static ng_constructor_t		nga_constructor;
98static ng_rcvdata_t		nga_rcvdata;
99static ng_rcvmsg_t		nga_rcvmsg;
100static ng_shutdown_t		nga_shutdown;
101static ng_newhook_t		nga_newhook;
102static ng_disconnect_t		nga_disconnect;
103
104/* Helper stuff */
105static int	nga_rcv_sync(const sc_p sc, item_p item);
106static int	nga_rcv_async(const sc_p sc, item_p item);
107
108/* Parse type for struct ng_async_cfg */
109static const struct ng_parse_struct_field nga_config_type_fields[]
110	= NG_ASYNC_CONFIG_TYPE_INFO;
111static const struct ng_parse_type nga_config_type = {
112	&ng_parse_struct_type,
113	&nga_config_type_fields
114};
115
116/* Parse type for struct ng_async_stat */
117static const struct ng_parse_struct_field nga_stats_type_fields[]
118	= NG_ASYNC_STATS_TYPE_INFO;
119static const struct ng_parse_type nga_stats_type = {
120	&ng_parse_struct_type,
121	&nga_stats_type_fields
122};
123
124/* List of commands and how to convert arguments to/from ASCII */
125static const struct ng_cmdlist nga_cmdlist[] = {
126	{
127	  NGM_ASYNC_COOKIE,
128	  NGM_ASYNC_CMD_SET_CONFIG,
129	  "setconfig",
130	  &nga_config_type,
131	  NULL
132	},
133	{
134	  NGM_ASYNC_COOKIE,
135	  NGM_ASYNC_CMD_GET_CONFIG,
136	  "getconfig",
137	  NULL,
138	  &nga_config_type
139	},
140	{
141	  NGM_ASYNC_COOKIE,
142	  NGM_ASYNC_CMD_GET_STATS,
143	  "getstats",
144	  NULL,
145	  &nga_stats_type
146	},
147	{
148	  NGM_ASYNC_COOKIE,
149	  NGM_ASYNC_CMD_CLR_STATS,
150	  "clrstats",
151	  &nga_stats_type,
152	  NULL
153	},
154	{ 0 }
155};
156
157/* Define the netgraph node type */
158static struct ng_type typestruct = {
159	.version =	NG_ABI_VERSION,
160	.name =		NG_ASYNC_NODE_TYPE,
161	.constructor =	nga_constructor,
162	.rcvmsg =	nga_rcvmsg,
163	.shutdown = 	nga_shutdown,
164	.newhook =	nga_newhook,
165	.rcvdata =	nga_rcvdata,
166	.disconnect =	nga_disconnect,
167	.cmdlist =	nga_cmdlist
168};
169NETGRAPH_INIT(async, &typestruct);
170
171/* CRC table */
172static const u_int16_t fcstab[];
173
174/******************************************************************
175		    NETGRAPH NODE METHODS
176******************************************************************/
177
178/*
179 * Initialize a new node
180 */
181static int
182nga_constructor(node_p node)
183{
184	sc_p sc;
185
186	sc = malloc(sizeof(*sc), M_NETGRAPH_ASYNC, M_WAITOK | M_ZERO);
187	sc->amode = MODE_HUNT;
188	sc->cfg.accm = ~0;
189	sc->cfg.amru = NG_ASYNC_DEFAULT_MRU;
190	sc->cfg.smru = NG_ASYNC_DEFAULT_MRU;
191	sc->abuf = malloc(ASYNC_BUF_SIZE(sc->cfg.smru),
192	    M_NETGRAPH_ASYNC, M_WAITOK);
193	sc->sbuf = malloc(SYNC_BUF_SIZE(sc->cfg.amru),
194	    M_NETGRAPH_ASYNC, M_WAITOK);
195	NG_NODE_SET_PRIVATE(node, sc);
196	sc->node = node;
197	return (0);
198}
199
200/*
201 * Reserve a hook for a pending connection
202 */
203static int
204nga_newhook(node_p node, hook_p hook, const char *name)
205{
206	const sc_p sc = NG_NODE_PRIVATE(node);
207	hook_p *hookp;
208
209	if (!strcmp(name, NG_ASYNC_HOOK_ASYNC)) {
210		/*
211		 * We use a static buffer here so only one packet
212		 * at a time can be allowed to travel in this direction.
213		 * Force Writer semantics.
214		 */
215		NG_HOOK_FORCE_WRITER(hook);
216		hookp = &sc->async;
217	} else if (!strcmp(name, NG_ASYNC_HOOK_SYNC)) {
218		/*
219		 * We use a static state here so only one packet
220		 * at a time can be allowed to travel in this direction.
221		 * Force Writer semantics.
222		 * Since we set this for both directions
223		 * we might as well set it for the whole node
224		 * bit I haven;t done that (yet).
225		 */
226		NG_HOOK_FORCE_WRITER(hook);
227		hookp = &sc->sync;
228	} else {
229		return (EINVAL);
230	}
231	if (*hookp) /* actually can't happen I think [JRE] */
232		return (EISCONN);
233	*hookp = hook;
234	return (0);
235}
236
237/*
238 * Receive incoming data
239 */
240static int
241nga_rcvdata(hook_p hook, item_p item)
242{
243	const sc_p sc = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
244
245	if (hook == sc->sync)
246		return (nga_rcv_sync(sc, item));
247	if (hook == sc->async)
248		return (nga_rcv_async(sc, item));
249	panic("%s", __func__);
250}
251
252/*
253 * Receive incoming control message
254 */
255static int
256nga_rcvmsg(node_p node, item_p item, hook_p lasthook)
257{
258	const sc_p sc = NG_NODE_PRIVATE(node);
259	struct ng_mesg *resp = NULL;
260	int error = 0;
261	struct ng_mesg *msg;
262
263	NGI_GET_MSG(item, msg);
264	switch (msg->header.typecookie) {
265	case NGM_ASYNC_COOKIE:
266		switch (msg->header.cmd) {
267		case NGM_ASYNC_CMD_GET_STATS:
268			NG_MKRESPONSE(resp, msg, sizeof(sc->stats), M_NOWAIT);
269			if (resp == NULL)
270				ERROUT(ENOMEM);
271			*((struct ng_async_stat *) resp->data) = sc->stats;
272			break;
273		case NGM_ASYNC_CMD_CLR_STATS:
274			bzero(&sc->stats, sizeof(sc->stats));
275			break;
276		case NGM_ASYNC_CMD_SET_CONFIG:
277		    {
278			struct ng_async_cfg *const cfg =
279				(struct ng_async_cfg *) msg->data;
280			u_char *buf;
281
282			if (msg->header.arglen != sizeof(*cfg))
283				ERROUT(EINVAL);
284			if (cfg->amru < NG_ASYNC_MIN_MRU
285			    || cfg->amru > NG_ASYNC_MAX_MRU
286			    || cfg->smru < NG_ASYNC_MIN_MRU
287			    || cfg->smru > NG_ASYNC_MAX_MRU)
288				ERROUT(EINVAL);
289			cfg->enabled = !!cfg->enabled;	/* normalize */
290			if (cfg->smru > sc->cfg.smru) {	/* reallocate buffer */
291				buf = malloc(ASYNC_BUF_SIZE(cfg->smru),
292				    M_NETGRAPH_ASYNC, M_NOWAIT);
293				if (!buf)
294					ERROUT(ENOMEM);
295				free(sc->abuf, M_NETGRAPH_ASYNC);
296				sc->abuf = buf;
297			}
298			if (cfg->amru > sc->cfg.amru) {	/* reallocate buffer */
299				buf = malloc(SYNC_BUF_SIZE(cfg->amru),
300				    M_NETGRAPH_ASYNC, M_NOWAIT);
301				if (!buf)
302					ERROUT(ENOMEM);
303				free(sc->sbuf, M_NETGRAPH_ASYNC);
304				sc->sbuf = buf;
305				sc->amode = MODE_HUNT;
306				sc->slen = 0;
307			}
308			if (!cfg->enabled) {
309				sc->amode = MODE_HUNT;
310				sc->slen = 0;
311			}
312			sc->cfg = *cfg;
313			break;
314		    }
315		case NGM_ASYNC_CMD_GET_CONFIG:
316			NG_MKRESPONSE(resp, msg, sizeof(sc->cfg), M_NOWAIT);
317			if (!resp)
318				ERROUT(ENOMEM);
319			*((struct ng_async_cfg *) resp->data) = sc->cfg;
320			break;
321		default:
322			ERROUT(EINVAL);
323		}
324		break;
325	default:
326		ERROUT(EINVAL);
327	}
328done:
329	NG_RESPOND_MSG(error, node, item, resp);
330	NG_FREE_MSG(msg);
331	return (error);
332}
333
334/*
335 * Shutdown this node
336 */
337static int
338nga_shutdown(node_p node)
339{
340	const sc_p sc = NG_NODE_PRIVATE(node);
341
342	free(sc->abuf, M_NETGRAPH_ASYNC);
343	free(sc->sbuf, M_NETGRAPH_ASYNC);
344	bzero(sc, sizeof(*sc));
345	free(sc, M_NETGRAPH_ASYNC);
346	NG_NODE_SET_PRIVATE(node, NULL);
347	NG_NODE_UNREF(node);
348	return (0);
349}
350
351/*
352 * Lose a hook. When both hooks go away, we disappear.
353 */
354static int
355nga_disconnect(hook_p hook)
356{
357	const sc_p sc = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
358	hook_p *hookp;
359
360	if (hook == sc->async)
361		hookp = &sc->async;
362	else if (hook == sc->sync)
363		hookp = &sc->sync;
364	else
365		panic("%s", __func__);
366	if (!*hookp)
367		panic("%s 2", __func__);
368	*hookp = NULL;
369	bzero(&sc->stats, sizeof(sc->stats));
370	sc->lasttime = 0;
371	if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0)
372	&& (NG_NODE_IS_VALID(NG_HOOK_NODE(hook))))
373		ng_rmnode_self(NG_HOOK_NODE(hook));
374	return (0);
375}
376
377/******************************************************************
378		    INTERNAL HELPER STUFF
379******************************************************************/
380
381/*
382 * Encode a byte into the async buffer
383 */
384static __inline void
385nga_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 */
400static int
401nga_rcv_sync(const sc_p sc, item_p item)
402{
403	struct ifnet *rcvif;
404	int alen, error = 0;
405	struct timeval time;
406	u_int16_t fcs, fcs0;
407	u_int32_t accm;
408	struct mbuf *m;
409
410
411#define ADD_BYTE(x)	nga_async_add(sc, &fcs, accm, &alen, (x))
412
413	/* Check for bypass mode */
414	if (!sc->cfg.enabled) {
415		NG_FWD_ITEM_HOOK(error, item, sc->async );
416		return (error);
417	}
418	NGI_GET_M(item, m);
419
420	rcvif = m->m_pkthdr.rcvif;
421
422	/* Get ACCM; special case LCP frames, which use full ACCM */
423	accm = sc->cfg.accm;
424	if (m->m_pkthdr.len >= 4) {
425		static const u_char lcphdr[4] = {
426		    PPP_ALLSTATIONS,
427		    PPP_UI,
428		    (u_char)(PPP_LCP >> 8),
429		    (u_char)(PPP_LCP & 0xff)
430		};
431		u_char buf[4];
432
433		m_copydata(m, 0, 4, (caddr_t)buf);
434		if (bcmp(buf, &lcphdr, 4) == 0)
435			accm = ~0;
436	}
437
438	/* Check for overflow */
439	if (m->m_pkthdr.len > sc->cfg.smru) {
440		sc->stats.syncOverflows++;
441		NG_FREE_M(m);
442		NG_FREE_ITEM(item);
443		return (EMSGSIZE);
444	}
445
446	/* Update stats */
447	sc->stats.syncFrames++;
448	sc->stats.syncOctets += m->m_pkthdr.len;
449
450	/* Initialize async encoded version of input mbuf */
451	alen = 0;
452	fcs = PPP_INITFCS;
453
454	/* Add beginning sync flag if it's been long enough to need one */
455	getmicrotime(&time);
456	if (time.tv_sec >= sc->lasttime + 1) {
457		sc->abuf[alen++] = PPP_FLAG;
458		sc->lasttime = time.tv_sec;
459	}
460
461	/* Add packet payload */
462	while (m != NULL) {
463		while (m->m_len > 0) {
464			ADD_BYTE(*mtod(m, u_char *));
465			m->m_data++;
466			m->m_len--;
467		}
468		m = m_free(m);
469	}
470
471	/* Add checksum and final sync flag */
472	fcs0 = fcs;
473	ADD_BYTE(~fcs0 & 0xff);
474	ADD_BYTE(~fcs0 >> 8);
475	sc->abuf[alen++] = PPP_FLAG;
476
477	/* Put frame in an mbuf and ship it off */
478	if (!(m = m_devget(sc->abuf, alen, 0, rcvif, NULL))) {
479		NG_FREE_ITEM(item);
480		error = ENOBUFS;
481	} else {
482		NG_FWD_NEW_DATA(error, item, sc->async, m);
483	}
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 */
492static int
493nga_rcv_async(const sc_p sc, item_p item)
494{
495	struct ifnet *rcvif;
496	int error;
497	struct mbuf *m;
498
499	if (!sc->cfg.enabled) {
500		NG_FWD_ITEM_HOOK(error, item,  sc->sync);
501		return (error);
502	}
503	NGI_GET_M(item, m);
504	rcvif = m->m_pkthdr.rcvif;
505	while (m) {
506		struct mbuf *n;
507
508		for (; m->m_len > 0; m->m_data++, m->m_len--) {
509			u_char  ch = *mtod(m, u_char *);
510
511			sc->stats.asyncOctets++;
512			if (ch == PPP_FLAG) {	/* Flag overrides everything */
513				int     skip = 0;
514
515				/* Check for runts */
516				if (sc->slen < 2) {
517					if (sc->slen > 0)
518						sc->stats.asyncRunts++;
519					goto reset;
520				}
521
522				/* Verify CRC */
523				if (sc->fcs != PPP_GOODFCS) {
524					sc->stats.asyncBadCheckSums++;
525					goto reset;
526				}
527				sc->slen -= 2;
528
529				/* Strip address and control fields */
530				if (sc->slen >= 2
531				    && sc->sbuf[0] == PPP_ALLSTATIONS
532				    && sc->sbuf[1] == PPP_UI)
533					skip = 2;
534
535				/* Check for frame too big */
536				if (sc->slen - skip > sc->cfg.amru) {
537					sc->stats.asyncOverflows++;
538					goto reset;
539				}
540
541				/* OK, ship it out */
542				if ((n = m_devget(sc->sbuf + skip,
543					   sc->slen - skip, 0, rcvif, NULL))) {
544					if (item) { /* sets NULL -> item */
545						NG_FWD_NEW_DATA(error, item,
546							sc->sync, n);
547					} else {
548						NG_SEND_DATA_ONLY(error,
549							sc->sync ,n);
550					}
551				}
552				sc->stats.asyncFrames++;
553reset:
554				sc->amode = MODE_NORMAL;
555				sc->fcs = PPP_INITFCS;
556				sc->slen = 0;
557				continue;
558			}
559			switch (sc->amode) {
560			case MODE_NORMAL:
561				if (ch == PPP_ESCAPE) {
562					sc->amode = MODE_ESC;
563					continue;
564				}
565				break;
566			case MODE_ESC:
567				ch ^= PPP_TRANS;
568				sc->amode = MODE_NORMAL;
569				break;
570			case MODE_HUNT:
571			default:
572				continue;
573			}
574
575			/* Add byte to frame */
576			if (sc->slen >= SYNC_BUF_SIZE(sc->cfg.amru)) {
577				sc->stats.asyncOverflows++;
578				sc->amode = MODE_HUNT;
579				sc->slen = 0;
580			} else {
581				sc->sbuf[sc->slen++] = ch;
582				sc->fcs = PPP_FCS(sc->fcs, ch);
583			}
584		}
585		m = m_free(m);
586	}
587	if (item)
588		NG_FREE_ITEM(item);
589	return (0);
590}
591
592/*
593 * CRC table
594 *
595 * Taken from RFC 1171 Appendix B
596 */
597static const u_int16_t fcstab[256] = {
598	 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
599	 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
600	 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
601	 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
602	 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
603	 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
604	 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
605	 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
606	 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
607	 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
608	 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
609	 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
610	 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
611	 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
612	 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
613	 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
614	 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
615	 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
616	 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
617	 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
618	 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
619	 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
620	 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
621	 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
622	 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
623	 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
624	 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
625	 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
626	 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
627	 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
628	 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
629	 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
630};
631