1254219Scy/*
2254219Scy * Copyright (C) 2012 by Darren Reed.
3254219Scy *
4254219Scy * See the IPFILTER.LICENCE file for details on licencing.
5254219Scy */
6254219Scy#if !defined(lint)
7254219Scystatic const char sccsid[] = "@(#)ip_fil.c	2.41 6/5/96 (C) 1993-2000 Darren Reed";
8254219Scystatic const char rcsid[] = "@(#)$Id: ipfsyncd.c,v 1.1.2.2 2012/07/22 08:04:24 darren_r Exp $";
9254219Scy#endif
10254219Scy#include <sys/types.h>
11254219Scy#include <sys/time.h>
12254219Scy#include <sys/socket.h>
13254219Scy#include <sys/ioctl.h>
14254219Scy#include <sys/sockio.h>
15254219Scy#include <sys/errno.h>
16254219Scy
17254219Scy#include <netinet/in.h>
18254219Scy#include <net/if.h>
19254219Scy
20254219Scy#include <arpa/inet.h>
21254219Scy
22254219Scy#include <stdio.h>
23254219Scy#include <stdlib.h>
24254219Scy#include <fcntl.h>
25254219Scy#include <unistd.h>
26254219Scy#include <string.h>
27254219Scy#include <syslog.h>
28254219Scy#include <signal.h>
29254219Scy
30254219Scy#include "ipf.h"
31254219Scy#include "opts.h"
32254219Scy
33254219Scy
34254219Scy#define	R_IO_ERROR	-1
35254219Scy#define	R_OKAY		0
36254219Scy#define	R_MORE		1
37254219Scy#define	R_SKIP		2
38254219Scy#if	defined(sun) && !defined(SOLARIS2)
39254219Scy# define	STRERROR(x)     sys_errlist[x]
40254219Scyextern  char    *sys_errlist[];
41254219Scy#else
42254219Scy# define	STRERROR(x)     strerror(x)
43254219Scy#endif
44254219Scy
45254219Scy
46369245Sgit2svnint	main(int, char *[]);
47369245Sgit2svnvoid	usage(char *);
48369245Sgit2svnvoid	printsynchdr(synchdr_t *);
49369245Sgit2svnvoid	printtable(int);
50369245Sgit2svnvoid	printsmcproto(char *);
51369245Sgit2svnvoid	printcommand(int);
52369245Sgit2svnint	do_kbuff(int, char *, int *);
53369245Sgit2svnint	do_packet(int, char *);
54369245Sgit2svnint	buildsocket(char *, struct sockaddr_in *);
55369245Sgit2svnvoid	do_io(void);
56369245Sgit2svnvoid	handleterm(int);
57254219Scy
58254219Scyint	terminate = 0;
59254219Scyint	igmpfd = -1;
60254219Scyint	nfd = -1;
61254219Scyint	lfd = -1;
62254219Scyint	opts = 0;
63254219Scy
64254219Scyvoid
65254219Scyusage(progname)
66254219Scy	char *progname;
67254219Scy{
68254219Scy	fprintf(stderr,
69254219Scy		"Usage: %s [-d] [-p port] [-i address] -I <interface>\n",
70254219Scy		progname);
71254219Scy}
72254219Scy
73254219Scyvoid
74254219Scyhandleterm(sig)
75254219Scy	int sig;
76254219Scy{
77254219Scy	terminate = sig;
78254219Scy}
79254219Scy
80254219Scy
81254219Scy/* should be large enough to hold header + any datatype */
82254219Scy#define BUFFERLEN 1400
83254219Scy
84254219Scyint
85254219Scymain(argc, argv)
86254219Scy	int argc;
87254219Scy	char *argv[];
88254219Scy{
89254219Scy	struct sockaddr_in sin;
90254219Scy	char *interface;
91254219Scy	char *progname;
92254219Scy	int opt, tries;
93254219Scy
94254219Scy	progname = strrchr(argv[0], '/');
95254219Scy	if (progname) {
96254219Scy		progname++;
97254219Scy	} else {
98254219Scy		progname = argv[0];
99254219Scy	}
100254219Scy
101254219Scy	opts = 0;
102254219Scy	tries = 0;
103254219Scy	interface = NULL;
104254219Scy
105254219Scy	bzero((char *)&sin, sizeof(sin));
106254219Scy	sin.sin_family = AF_INET;
107254219Scy	sin.sin_port = htons(0xaf6c);
108254219Scy	sin.sin_addr.s_addr = htonl(INADDR_UNSPEC_GROUP | 0x697066);
109254219Scy
110254219Scy	while ((opt = getopt(argc, argv, "di:I:p:")) != -1)
111254219Scy		switch (opt)
112254219Scy		{
113254219Scy		case 'd' :
114254219Scy			debuglevel++;
115254219Scy			break;
116254219Scy		case 'I' :
117254219Scy			interface = optarg;
118254219Scy			break;
119254219Scy		case 'i' :
120254219Scy			sin.sin_addr.s_addr = inet_addr(optarg);
121254219Scy			break;
122254219Scy		case 'p' :
123254219Scy			sin.sin_port = htons(atoi(optarg));
124254219Scy			break;
125254219Scy		}
126254219Scy
127254219Scy	if (interface == NULL) {
128254219Scy		usage(progname);
129254219Scy		exit(1);
130254219Scy	}
131254219Scy
132254219Scy	if (!debuglevel) {
133254219Scy
134369273Scy#ifdef BSD
135254219Scy		daemon(0, 0);
136254219Scy#else
137254219Scy		int fd = open("/dev/null", O_RDWR);
138254219Scy
139254219Scy		switch (fork())
140254219Scy		{
141254219Scy		case 0 :
142254219Scy			break;
143254219Scy
144254219Scy		case -1 :
145254219Scy			fprintf(stderr, "%s: fork() failed: %s\n",
146254219Scy				argv[0], STRERROR(errno));
147254219Scy			exit(1);
148254219Scy			/* NOTREACHED */
149254219Scy
150254219Scy		default :
151254219Scy			exit(0);
152254219Scy			/* NOTREACHED */
153254219Scy		}
154254219Scy
155254219Scy		dup2(fd, 0);
156254219Scy		dup2(fd, 1);
157254219Scy		dup2(fd, 2);
158254219Scy		close(fd);
159254219Scy
160254219Scy		setsid();
161254219Scy#endif
162254219Scy	}
163254219Scy
164254219Scy       	signal(SIGHUP, handleterm);
165254219Scy       	signal(SIGINT, handleterm);
166254219Scy       	signal(SIGTERM, handleterm);
167254219Scy
168254219Scy	openlog(progname, LOG_PID, LOG_SECURITY);
169254219Scy
170254219Scy	while (!terminate) {
171254219Scy		if (lfd != -1) {
172254219Scy			close(lfd);
173254219Scy			lfd = -1;
174254219Scy		}
175254219Scy		if (nfd != -1) {
176254219Scy			close(nfd);
177254219Scy			nfd = -1;
178254219Scy		}
179254219Scy		if (igmpfd != -1) {
180254219Scy			close(igmpfd);
181254219Scy			igmpfd = -1;
182254219Scy		}
183254219Scy
184254219Scy		if (buildsocket(interface, &sin) == -1)
185254219Scy			goto tryagain;
186254219Scy
187254219Scy		lfd = open(IPSYNC_NAME, O_RDWR);
188254219Scy		if (lfd == -1) {
189254219Scy			syslog(LOG_ERR, "open(%s):%m", IPSYNC_NAME);
190254219Scy			debug(1, "open(%s): %s\n", IPSYNC_NAME,
191254219Scy			      STRERROR(errno));
192254219Scy			goto tryagain;
193254219Scy		}
194254219Scy
195254219Scy		tries = -1;
196254219Scy		do_io();
197254219Scytryagain:
198254219Scy		tries++;
199254219Scy		syslog(LOG_INFO, "retry in %d seconds", 1 << tries);
200254219Scy		debug(1, "wait %d seconds\n", 1 << tries);
201254219Scy		sleep(1 << tries);
202254219Scy	}
203254219Scy
204254219Scy
205254219Scy	/* terminate */
206254219Scy	if (lfd != -1)
207254219Scy		close(lfd);
208254219Scy	if (nfd != -1)
209254219Scy		close(nfd);
210254219Scy
211254219Scy	syslog(LOG_ERR, "signal %d received, exiting...", terminate);
212254219Scy	debug(1, "signal %d received, exiting...", terminate);
213254219Scy
214254219Scy	exit(1);
215254219Scy}
216254219Scy
217254219Scy
218254219Scyvoid
219254219Scydo_io()
220254219Scy{
221254219Scy	char nbuff[BUFFERLEN];
222254219Scy	char buff[BUFFERLEN];
223254219Scy	fd_set mrd, rd;
224254219Scy	int maxfd;
225254219Scy	int inbuf;
226254219Scy	int n1;
227254219Scy	int left;
228254219Scy
229254219Scy	FD_ZERO(&mrd);
230254219Scy	FD_SET(lfd, &mrd);
231254219Scy	FD_SET(nfd, &mrd);
232254219Scy	maxfd = nfd;
233254219Scy	if (lfd > maxfd)
234254219Scy		maxfd = lfd;
235254219Scy	debug(2, "nfd %d lfd %d maxfd %d\n", nfd, lfd, maxfd);
236254219Scy
237254219Scy	inbuf = 0;
238254219Scy	/*
239254219Scy	 * A threaded approach to this loop would have one thread
240254219Scy	 * work on reading lfd (only) all the time and another thread
241254219Scy	 * working on reading nfd all the time.
242254219Scy	 */
243254219Scy	while (!terminate) {
244254219Scy		int n;
245254219Scy
246254219Scy		rd = mrd;
247254219Scy
248254219Scy		n = select(maxfd + 1, &rd, NULL, NULL, NULL);
249254219Scy		if (n < 0) {
250254219Scy			switch (errno)
251254219Scy			{
252254219Scy			case EINTR :
253254219Scy				continue;
254254219Scy			default :
255254219Scy				syslog(LOG_ERR, "select error: %m");
256254219Scy				debug(1, "select error: %s\n", STRERROR(errno));
257254219Scy				return;
258254219Scy			}
259254219Scy		}
260254219Scy
261254219Scy		if (FD_ISSET(lfd, &rd)) {
262254219Scy			n1 = read(lfd, buff+inbuf, BUFFERLEN-inbuf);
263254219Scy
264254219Scy			debug(3, "read(K):%d\n", n1);
265254219Scy
266254219Scy			if (n1 <= 0) {
267254219Scy				syslog(LOG_ERR, "read error (k-header): %m");
268254219Scy				debug(1, "read error (k-header): %s\n",
269254219Scy				      STRERROR(errno));
270254219Scy				return;
271254219Scy			}
272254219Scy
273254219Scy			left = 0;
274254219Scy
275254219Scy			switch (do_kbuff(n1, buff, &left))
276254219Scy			{
277254219Scy			case R_IO_ERROR :
278254219Scy				return;
279254219Scy			case R_MORE :
280254219Scy				inbuf += left;
281254219Scy				break;
282254219Scy			default :
283254219Scy				inbuf = 0;
284254219Scy				break;
285254219Scy			}
286254219Scy		}
287254219Scy
288254219Scy		if (FD_ISSET(nfd, &rd)) {
289254219Scy			n1 = recv(nfd, nbuff, sizeof(nbuff), 0);
290254219Scy
291254219Scy			debug(3, "read(N):%d\n", n1);
292254219Scy
293254219Scy			if (n1 <= 0) {
294254219Scy				syslog(LOG_ERR, "read error (n-header): %m");
295254219Scy				debug(1, "read error (n-header): %s\n",
296254219Scy				      STRERROR(errno));
297254219Scy				return;
298254219Scy			}
299254219Scy
300254219Scy			switch (do_packet(n1, nbuff))
301254219Scy			{
302254219Scy			case R_IO_ERROR :
303254219Scy				return;
304254219Scy			default :
305254219Scy				break;
306254219Scy			}
307254219Scy		}
308254219Scy	}
309254219Scy}
310254219Scy
311254219Scy
312254219Scyint
313254219Scybuildsocket(nicname, sinp)
314254219Scy	char *nicname;
315254219Scy	struct sockaddr_in *sinp;
316254219Scy{
317254219Scy	struct sockaddr_in *reqip;
318254219Scy	struct ifreq req;
319254219Scy	char opt;
320254219Scy
321254219Scy	debug(2, "binding to %s:%s\n", nicname, inet_ntoa(sinp->sin_addr));
322254219Scy
323254219Scy	if (IN_MULTICAST(ntohl(sinp->sin_addr.s_addr))) {
324254219Scy		struct in_addr addr;
325254219Scy		struct ip_mreq mreq;
326254219Scy
327254219Scy		igmpfd = socket(AF_INET, SOCK_RAW, IPPROTO_IGMP);
328254219Scy		if (igmpfd == -1) {
329254219Scy			syslog(LOG_ERR, "socket:%m");
330254219Scy			debug(1, "socket:%s\n", STRERROR(errno));
331254219Scy			return -1;
332254219Scy		}
333254219Scy
334254219Scy		bzero((char *)&req, sizeof(req));
335254219Scy		strncpy(req.ifr_name, nicname, sizeof(req.ifr_name));
336254219Scy		req.ifr_name[sizeof(req.ifr_name) - 1] = '\0';
337254219Scy		if (ioctl(igmpfd, SIOCGIFADDR, &req) == -1) {
338254219Scy			syslog(LOG_ERR, "ioctl(SIOCGIFADDR):%m");
339254219Scy			debug(1, "ioctl(SIOCGIFADDR):%s\n", STRERROR(errno));
340254219Scy			close(igmpfd);
341254219Scy			igmpfd = -1;
342254219Scy			return -1;
343254219Scy		}
344254219Scy		reqip = (struct sockaddr_in *)&req.ifr_addr;
345254219Scy
346254219Scy		addr = reqip->sin_addr;
347254219Scy		if (setsockopt(igmpfd, IPPROTO_IP, IP_MULTICAST_IF,
348254219Scy			       (char *)&addr, sizeof(addr)) == -1) {
349254219Scy			syslog(LOG_ERR, "setsockopt(IP_MULTICAST_IF(%s)):%m",
350254219Scy			       inet_ntoa(addr));
351254219Scy			debug(1, "setsockopt(IP_MULTICAST_IF(%s)):%s\n",
352254219Scy			      inet_ntoa(addr), STRERROR(errno));
353254219Scy			close(igmpfd);
354254219Scy			igmpfd = -1;
355254219Scy			return -1;
356254219Scy		}
357254219Scy
358254219Scy		opt = 0;
359254219Scy		if (setsockopt(igmpfd, IPPROTO_IP, IP_MULTICAST_LOOP,
360254219Scy			       (char *)&opt, sizeof(opt)) == -1) {
361254219Scy			syslog(LOG_ERR, "setsockopt(IP_MULTICAST_LOOP=0):%m");
362254219Scy			debug(1, "setsockopt(IP_MULTICAST_LOOP=0):%s\n",
363254219Scy			      STRERROR(errno));
364254219Scy			close(igmpfd);
365254219Scy			igmpfd = -1;
366254219Scy			return -1;
367254219Scy		}
368254219Scy
369254219Scy		opt = 63;
370254219Scy		if (setsockopt(igmpfd, IPPROTO_IP, IP_MULTICAST_TTL,
371254219Scy			       (char *)&opt, sizeof(opt)) == -1) {
372254219Scy			syslog(LOG_ERR, "setsockopt(IP_MULTICAST_TTL=%d):%m",
373254219Scy			       opt);
374254219Scy			debug(1, "setsockopt(IP_MULTICAST_TTL=%d):%s\n", opt,
375254219Scy			      STRERROR(errno));
376254219Scy			close(igmpfd);
377254219Scy			igmpfd = -1;
378254219Scy			return -1;
379254219Scy		}
380254219Scy
381254219Scy		mreq.imr_multiaddr.s_addr = sinp->sin_addr.s_addr;
382254219Scy		mreq.imr_interface.s_addr = reqip->sin_addr.s_addr;
383254219Scy
384254219Scy		if (setsockopt(igmpfd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
385254219Scy			       (char *)&mreq, sizeof(mreq)) == -1) {
386254219Scy			char buffer[80];
387254219Scy
388254219Scy			sprintf(buffer, "%s,", inet_ntoa(sinp->sin_addr));
389254219Scy			strcat(buffer, inet_ntoa(reqip->sin_addr));
390254219Scy
391254219Scy			syslog(LOG_ERR,
392254219Scy			       "setsockpt(IP_ADD_MEMBERSHIP,%s):%m", buffer);
393254219Scy			debug(1, "setsockpt(IP_ADD_MEMBERSHIP,%s):%s\n",
394254219Scy			      buffer, STRERROR(errno));
395254219Scy			close(igmpfd);
396254219Scy			igmpfd = -1;
397254219Scy			return -1;
398254219Scy		}
399254219Scy	}
400254219Scy	nfd = socket(AF_INET, SOCK_DGRAM, 0);
401254219Scy	if (nfd == -1) {
402254219Scy		syslog(LOG_ERR, "socket:%m");
403254219Scy		if (igmpfd != -1) {
404254219Scy			close(igmpfd);
405254219Scy			igmpfd = -1;
406254219Scy		}
407254219Scy		return -1;
408254219Scy	}
409254219Scy	bzero((char *)&req, sizeof(req));
410254219Scy	strncpy(req.ifr_name, nicname, sizeof(req.ifr_name));
411254219Scy	req.ifr_name[sizeof(req.ifr_name) - 1] = '\0';
412254219Scy	if (ioctl(nfd, SIOCGIFADDR, &req) == -1) {
413254219Scy		syslog(LOG_ERR, "ioctl(SIOCGIFADDR):%m");
414254219Scy		debug(1, "ioctl(SIOCGIFADDR):%s\n", STRERROR(errno));
415254219Scy		close(igmpfd);
416254219Scy		igmpfd = -1;
417254219Scy		return -1;
418254219Scy	}
419254219Scy
420254219Scy	if (bind(nfd, (struct sockaddr *)&req.ifr_addr,
421254219Scy		 sizeof(req.ifr_addr)) == -1) {
422254219Scy		syslog(LOG_ERR, "bind:%m");
423254219Scy		debug(1, "bind:%s\n", STRERROR(errno));
424254219Scy		close(nfd);
425254219Scy		if (igmpfd != -1) {
426254219Scy			close(igmpfd);
427254219Scy			igmpfd = -1;
428254219Scy		}
429254219Scy		nfd = -1;
430254219Scy		return -1;
431254219Scy	}
432254219Scy
433254219Scy	if (connect(nfd, (struct sockaddr *)sinp, sizeof(*sinp)) == -1) {
434254219Scy		syslog(LOG_ERR, "connect:%m");
435254219Scy		debug(1, "connect:%s\n", STRERROR(errno));
436254219Scy		close(nfd);
437254219Scy		if (igmpfd != -1) {
438254219Scy			close(igmpfd);
439254219Scy			igmpfd = -1;
440254219Scy		}
441254219Scy		nfd = -1;
442254219Scy		return -1;
443254219Scy	}
444254219Scy	syslog(LOG_INFO, "Sending data to %s", inet_ntoa(sinp->sin_addr));
445254219Scy	debug(3, "Sending data to %s\n", inet_ntoa(sinp->sin_addr));
446254219Scy
447254219Scy	return nfd;
448254219Scy}
449254219Scy
450254219Scy
451254219Scyint
452254219Scydo_packet(pklen, buff)
453254219Scy	int pklen;
454254219Scy	char *buff;
455254219Scy{
456254219Scy	synchdr_t *sh;
457254219Scy	u_32_t magic;
458254219Scy	int len;
459254219Scy	int n2;
460254219Scy	int n3;
461254219Scy
462254219Scy	while (pklen > 0) {
463254219Scy		if (pklen < sizeof(*sh)) {
464254219Scy			syslog(LOG_ERR, "packet length too short:%d", pklen);
465254219Scy			debug(2, "packet length too short:%d\n", pklen);
466254219Scy			return R_SKIP;
467254219Scy		}
468254219Scy
469254219Scy		sh = (synchdr_t *)buff;
470254219Scy		len = ntohl(sh->sm_len);
471254219Scy		magic = ntohl(sh->sm_magic);
472254219Scy
473254219Scy		if (magic != SYNHDRMAGIC) {
474254219Scy			syslog(LOG_ERR, "invalid header magic %x", magic);
475254219Scy			debug(2, "invalid header magic %x\n", magic);
476254219Scy			return R_SKIP;
477254219Scy		}
478254219Scy
479254219Scy		if (pklen < len + sizeof(*sh)) {
480254219Scy			syslog(LOG_ERR, "packet length too short:%d", pklen);
481254219Scy			debug(2, "packet length too short:%d\n", pklen);
482254219Scy			return R_SKIP;
483254219Scy		}
484254219Scy
485254219Scy		if (debuglevel > 3) {
486254219Scy			printsynchdr(sh);
487254219Scy			printcommand(sh->sm_cmd);
488254219Scy			printtable(sh->sm_table);
489254219Scy			printsmcproto(buff);
490254219Scy		}
491254219Scy
492254219Scy		n2 = sizeof(*sh) + len;
493254219Scy
494254219Scy		do {
495254219Scy			n3 = write(lfd, buff, n2);
496254219Scy			if (n3 <= 0) {
497254219Scy				syslog(LOG_ERR, "write error: %m");
498254219Scy				debug(1, "write error: %s\n", STRERROR(errno));
499254219Scy				return R_IO_ERROR;
500254219Scy			}
501254219Scy
502254219Scy			n2 -= n3;
503254219Scy			buff += n3;
504254219Scy			pklen -= n3;
505254219Scy		} while (n3 != 0);
506254219Scy	}
507254219Scy
508254219Scy	return R_OKAY;
509254219Scy}
510254219Scy
511254219Scy
512254219Scy
513254219Scyint
514254219Scydo_kbuff(inbuf, buf, left)
515254219Scy	int inbuf, *left;
516254219Scy	char *buf;
517254219Scy{
518254219Scy	synchdr_t *sh;
519254219Scy	u_32_t magic;
520254219Scy	int complete;
521254219Scy	int sendlen;
522254219Scy	int error;
523254219Scy	int bytes;
524254219Scy	int len;
525254219Scy	int n2;
526254219Scy	int n3;
527254219Scy
528254219Scy	sendlen = 0;
529254219Scy	bytes = inbuf;
530254219Scy	error = R_OKAY;
531254219Scy	sh = (synchdr_t *)buf;
532254219Scy
533254219Scy	for (complete = 0; bytes > 0; complete++) {
534254219Scy		len = ntohl(sh->sm_len);
535254219Scy		magic = ntohl(sh->sm_magic);
536254219Scy
537254219Scy		if (magic != SYNHDRMAGIC) {
538254219Scy			syslog(LOG_ERR,
539254219Scy			       "read invalid header magic 0x%x, flushing",
540254219Scy			       magic);
541254219Scy			debug(2, "read invalid header magic 0x%x, flushing\n",
542254219Scy			       magic);
543254219Scy			n2 = SMC_RLOG;
544254219Scy			(void) ioctl(lfd, SIOCIPFFL, &n2);
545254219Scy			break;
546254219Scy		}
547254219Scy
548254219Scy		if (debuglevel > 3) {
549254219Scy			printsynchdr(sh);
550254219Scy			printcommand(sh->sm_cmd);
551254219Scy			printtable(sh->sm_table);
552254219Scy			putchar('\n');
553254219Scy		}
554254219Scy
555254219Scy		if (bytes < sizeof(*sh) + len) {
556254219Scy			debug(3, "Not enough bytes %d < %d\n", bytes,
557254219Scy			      sizeof(*sh) + len);
558254219Scy			error = R_MORE;
559254219Scy			break;
560254219Scy		}
561254219Scy
562254219Scy		if (debuglevel > 3) {
563254219Scy			printsmcproto(buf);
564254219Scy		}
565254219Scy
566254219Scy		sendlen += len + sizeof(*sh);
567254219Scy		sh = (synchdr_t *)(buf + sendlen);
568254219Scy		bytes -= sendlen;
569254219Scy	}
570254219Scy
571254219Scy	if (complete) {
572254219Scy		n3 = send(nfd, buf, sendlen, 0);
573254219Scy		if (n3 <= 0) {
574254219Scy			syslog(LOG_ERR, "write error: %m");
575254219Scy			debug(1, "write error: %s\n", STRERROR(errno));
576254219Scy			return R_IO_ERROR;
577254219Scy		}
578254219Scy		debug(3, "send on %d len %d = %d\n", nfd, sendlen, n3);
579254219Scy		error = R_OKAY;
580254219Scy	}
581254219Scy
582254219Scy	/* move buffer to the front,we might need to make
583254219Scy	 * this more efficient, by using a rolling pointer
584254219Scy	 * over the buffer and only copying it, when
585254219Scy	 * we are reaching the end
586254219Scy	 */
587254219Scy	if (bytes > 0) {
588254219Scy		bcopy(buf + bytes, buf, bytes);
589254219Scy		error = R_MORE;
590254219Scy	}
591254219Scy	debug(4, "complete %d bytes %d error %d\n", complete, bytes, error);
592254219Scy
593254219Scy	*left = bytes;
594254219Scy
595254219Scy	return error;
596254219Scy}
597254219Scy
598254219Scy
599254219Scyvoid
600254219Scyprintcommand(cmd)
601254219Scy	int cmd;
602254219Scy{
603254219Scy
604254219Scy	switch (cmd)
605254219Scy	{
606254219Scy	case SMC_CREATE :
607254219Scy		printf(" cmd:CREATE");
608254219Scy		break;
609254219Scy	case SMC_UPDATE :
610254219Scy		printf(" cmd:UPDATE");
611254219Scy		break;
612254219Scy	default :
613254219Scy		printf(" cmd:Unknown(%d)", cmd);
614254219Scy		break;
615254219Scy	}
616254219Scy}
617254219Scy
618254219Scy
619254219Scyvoid
620254219Scyprinttable(table)
621254219Scy	int table;
622254219Scy{
623254219Scy	switch (table)
624254219Scy	{
625254219Scy	case SMC_NAT :
626254219Scy		printf(" table:NAT");
627254219Scy		break;
628254219Scy	case SMC_STATE :
629254219Scy		printf(" table:STATE");
630254219Scy		break;
631254219Scy	default :
632254219Scy		printf(" table:Unknown(%d)", table);
633254219Scy		break;
634254219Scy	}
635254219Scy}
636254219Scy
637254219Scy
638254219Scyvoid
639254219Scyprintsmcproto(buff)
640254219Scy	char *buff;
641254219Scy{
642254219Scy	syncupdent_t *su;
643254219Scy	synchdr_t *sh;
644254219Scy
645254219Scy	sh = (synchdr_t *)buff;
646254219Scy
647254219Scy	if (sh->sm_cmd == SMC_CREATE) {
648254219Scy		;
649254219Scy
650254219Scy	} else if (sh->sm_cmd == SMC_UPDATE) {
651254219Scy		su = (syncupdent_t *)buff;
652254219Scy		if (sh->sm_p == IPPROTO_TCP) {
653254219Scy			printf(" TCP Update: age %lu state %d/%d\n",
654254219Scy				su->sup_tcp.stu_age,
655254219Scy				su->sup_tcp.stu_state[0],
656254219Scy				su->sup_tcp.stu_state[1]);
657254219Scy		}
658254219Scy	} else {
659254219Scy		printf("Unknown command\n");
660254219Scy	}
661254219Scy}
662254219Scy
663254219Scy
664254219Scyvoid
665254219Scyprintsynchdr(sh)
666254219Scy	synchdr_t *sh;
667254219Scy{
668254219Scy
669254219Scy	printf("v:%d p:%d num:%d len:%d magic:%x", sh->sm_v, sh->sm_p,
670254219Scy	       ntohl(sh->sm_num), ntohl(sh->sm_len), ntohl(sh->sm_magic));
671254219Scy}
672