1139825Simp/* 290643Sbenno * Copyright (C) 2012 by Darren Reed. 390643Sbenno * 490643Sbenno * See the IPFILTER.LICENCE file for details on licencing. 590643Sbenno */ 690643Sbenno#if !defined(lint) 790643Sbennostatic const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed"; 890643Sbennostatic const char rcsid[] = "@(#)$Id: ipfsyncd.c,v 1.1.2.2 2012/07/22 08:04:24 darren_r Exp $"; 990643Sbenno#endif 1090643Sbenno#include <sys/types.h> 1190643Sbenno#include <sys/time.h> 1290643Sbenno#include <sys/socket.h> 1390643Sbenno#include <sys/ioctl.h> 1490643Sbenno#include <sys/sockio.h> 1590643Sbenno#include <sys/errno.h> 1690643Sbenno 1790643Sbenno#include <netinet/in.h> 1890643Sbenno#include <net/if.h> 1990643Sbenno 2090643Sbenno#include <arpa/inet.h> 2190643Sbenno 2290643Sbenno#include <stdio.h> 2390643Sbenno#include <stdlib.h> 2490643Sbenno#include <fcntl.h> 2590643Sbenno#include <unistd.h> 2690643Sbenno#include <string.h> 2790643Sbenno#include <syslog.h> 2890643Sbenno#include <signal.h> 2990643Sbenno 3090643Sbenno#include "ipf.h" 3190643Sbenno#include "opts.h" 3290643Sbenno 3390643Sbenno 3490643Sbenno#define R_IO_ERROR -1 3590643Sbenno#define R_OKAY 0 36139825Simp#define R_MORE 1 3777957Sbenno#define R_SKIP 2 3877957Sbenno#if defined(sun) && !defined(SOLARIS2) 3977957Sbenno# define STRERROR(x) sys_errlist[x] 4077957Sbennoextern char *sys_errlist[]; 4177957Sbenno#else 4277957Sbenno# define STRERROR(x) strerror(x) 4377957Sbenno#endif 4477957Sbenno 4577957Sbenno 4677957Sbennoint main __P((int, char *[])); 4777957Sbennovoid usage __P((char *)); 4877957Sbennovoid printsynchdr __P((synchdr_t *)); 4977957Sbennovoid printtable __P((int)); 5077957Sbennovoid printsmcproto __P((char *)); 5177957Sbennovoid printcommand __P((int)); 5277957Sbennoint do_kbuff __P((int, char *, int *)); 5377957Sbennoint do_packet __P((int, char *)); 5477957Sbennoint buildsocket __P((char *, struct sockaddr_in *)); 5577957Sbennovoid do_io __P((void)); 5677957Sbennovoid handleterm __P((int)); 5777957Sbenno 5877957Sbennoint terminate = 0; 5977957Sbennoint igmpfd = -1; 6077957Sbennoint nfd = -1; 6177957Sbennoint lfd = -1; 6277957Sbennoint opts = 0; 6377957Sbenno 6477957Sbennovoid 6577957Sbennousage(progname) 6678880Sbenno char *progname; 6777957Sbenno{ 68139825Simp fprintf(stderr, 6977957Sbenno "Usage: %s [-d] [-p port] [-i address] -I <interface>\n", 7077957Sbenno progname); 7177957Sbenno} 7277957Sbenno 7377957Sbennovoid 7477957Sbennohandleterm(sig) 7577957Sbenno int sig; 7677957Sbenno{ 7777957Sbenno terminate = sig; 7877957Sbenno} 7977957Sbenno 8077957Sbenno 8177957Sbenno/* should be large enough to hold header + any datatype */ 8277957Sbenno#define BUFFERLEN 1400 8377957Sbenno 8477957Sbennoint 8577957Sbennomain(argc, argv) 8677957Sbenno int argc; 8777957Sbenno char *argv[]; 8877957Sbenno{ 8977957Sbenno struct sockaddr_in sin; 9077957Sbenno char *interface; 9177957Sbenno char *progname; 9277957Sbenno int opt, tries; 93113038Sobrien 94113038Sobrien progname = strrchr(argv[0], '/'); 9577957Sbenno if (progname) { 9690643Sbenno progname++; 9790643Sbenno } else { 9890643Sbenno progname = argv[0]; 9990643Sbenno } 10090643Sbenno 10190643Sbenno opts = 0; 10290643Sbenno tries = 0; 10390643Sbenno interface = NULL; 10490643Sbenno 10590643Sbenno bzero((char *)&sin, sizeof(sin)); 10690643Sbenno sin.sin_family = AF_INET; 10790643Sbenno sin.sin_port = htons(0xaf6c); 10890643Sbenno sin.sin_addr.s_addr = htonl(INADDR_UNSPEC_GROUP | 0x697066); 10990643Sbenno 11090643Sbenno while ((opt = getopt(argc, argv, "di:I:p:")) != -1) 11190643Sbenno switch (opt) 11290643Sbenno { 11390643Sbenno case 'd' : 11490643Sbenno debuglevel++; 11590643Sbenno break; 11690643Sbenno case 'I' : 117118239Speter interface = optarg; 118118239Speter break; 11977957Sbenno case 'i' : 12080431Speter sin.sin_addr.s_addr = inet_addr(optarg); 121222813Sattilio break; 122222813Sattilio case 'p' : 12390643Sbenno sin.sin_port = htons(atoi(optarg)); 12490643Sbenno break; 12590643Sbenno } 12690643Sbenno 12777957Sbenno if (interface == NULL) { 128222813Sattilio usage(progname); 12990643Sbenno exit(1); 13090643Sbenno } 13177957Sbenno 13277957Sbenno if (!debuglevel) { 13390643Sbenno 13490643Sbenno#if BSD >= 199306 135152180Sgrehan daemon(0, 0); 13677957Sbenno#else 13777957Sbenno int fd = open("/dev/null", O_RDWR); 13877957Sbenno 13977957Sbenno switch (fork()) 14077957Sbenno { 14177957Sbenno case 0 : 14277957Sbenno break; 14377957Sbenno 14492847Sjeff case -1 : 14577957Sbenno fprintf(stderr, "%s: fork() failed: %s\n", 146125687Sgrehan argv[0], STRERROR(errno)); 147192067Snwhitehorn exit(1); 14883730Smp /* NOTREACHED */ 14990643Sbenno 15090643Sbenno default : 15190643Sbenno exit(0); 15277957Sbenno /* NOTREACHED */ 153178628Smarcel } 15490643Sbenno 155152180Sgrehan dup2(fd, 0); 15677957Sbenno dup2(fd, 1); 157152180Sgrehan dup2(fd, 2); 15877957Sbenno close(fd); 159152180Sgrehan 160152180Sgrehan setsid(); 16190643Sbenno#endif 16277957Sbenno } 16390643Sbenno 16490643Sbenno signal(SIGHUP, handleterm); 16590643Sbenno signal(SIGINT, handleterm); 16690643Sbenno signal(SIGTERM, handleterm); 16790643Sbenno 16890643Sbenno openlog(progname, LOG_PID, LOG_SECURITY); 16990643Sbenno 17090643Sbenno while (!terminate) { 17190643Sbenno if (lfd != -1) { 17290643Sbenno close(lfd); 17377957Sbenno lfd = -1; 17490643Sbenno } 17590643Sbenno if (nfd != -1) { 17690643Sbenno close(nfd); 17797346Sbenno nfd = -1; 17897346Sbenno } 179209975Snwhitehorn if (igmpfd != -1) { 180209975Snwhitehorn close(igmpfd); 181100319Sbenno igmpfd = -1; 18277957Sbenno } 18390643Sbenno 184134535Salc if (buildsocket(interface, &sin) == -1) 185134535Salc goto tryagain; 186152180Sgrehan 187212278Snwhitehorn lfd = open(IPSYNC_NAME, O_RDWR); 188134535Salc if (lfd == -1) { 189183094Smarcel syslog(LOG_ERR, "open(%s):%m", IPSYNC_NAME); 190183094Smarcel debug(1, "open(%s): %s\n", IPSYNC_NAME, 191183094Smarcel STRERROR(errno)); 192134535Salc goto tryagain; 19390643Sbenno } 19490643Sbenno 195152180Sgrehan tries = -1; 196152180Sgrehan do_io(); 197152180Sgrehantryagain: 19877957Sbenno tries++; 19990643Sbenno syslog(LOG_INFO, "retry in %d seconds", 1 << tries); 20090643Sbenno debug(1, "wait %d seconds\n", 1 << tries); 20190643Sbenno sleep(1 << tries); 202152180Sgrehan } 203152180Sgrehan 204152180Sgrehan 20577957Sbenno /* terminate */ 206152180Sgrehan if (lfd != -1) 207152180Sgrehan close(lfd); 20877957Sbenno if (nfd != -1) 20999037Sbenno close(nfd); 210152180Sgrehan 211152180Sgrehan syslog(LOG_ERR, "signal %d received, exiting...", terminate); 21277957Sbenno debug(1, "signal %d received, exiting...", terminate); 21390643Sbenno 214152180Sgrehan exit(1); 21577957Sbenno} 216152180Sgrehan 21777957Sbenno 21890643Sbennovoid 21990643Sbennodo_io() 22090643Sbenno{ 221152180Sgrehan char nbuff[BUFFERLEN]; 222152180Sgrehan char buff[BUFFERLEN]; 223152180Sgrehan fd_set mrd, rd; 224152180Sgrehan int maxfd; 225152180Sgrehan int inbuf; 226152180Sgrehan int n1; 227152180Sgrehan int left; 228152180Sgrehan 22990643Sbenno FD_ZERO(&mrd); 230152180Sgrehan FD_SET(lfd, &mrd); 231152180Sgrehan FD_SET(nfd, &mrd); 232152180Sgrehan maxfd = nfd; 233152180Sgrehan if (lfd > maxfd) 234152180Sgrehan maxfd = lfd; 23590643Sbenno debug(2, "nfd %d lfd %d maxfd %d\n", nfd, lfd, maxfd); 236152180Sgrehan 237152180Sgrehan inbuf = 0; 238152180Sgrehan /* 239152180Sgrehan * A threaded approach to this loop would have one thread 240152180Sgrehan * work on reading lfd (only) all the time and another thread 241152180Sgrehan * working on reading nfd all the time. 24277957Sbenno */ 24390643Sbenno while (!terminate) { 244152180Sgrehan int n; 24590643Sbenno 246152180Sgrehan rd = mrd; 24777957Sbenno 24890643Sbenno n = select(maxfd + 1, &rd, NULL, NULL, NULL); 24990643Sbenno if (n < 0) { 25090643Sbenno switch (errno) 251152180Sgrehan { 25277957Sbenno case EINTR : 25377957Sbenno continue; 25490643Sbenno default : 25577957Sbenno syslog(LOG_ERR, "select error: %m"); 256152180Sgrehan debug(1, "select error: %s\n", STRERROR(errno)); 25790643Sbenno return; 258152180Sgrehan } 259152180Sgrehan } 260152180Sgrehan 26190643Sbenno if (FD_ISSET(lfd, &rd)) { 26290643Sbenno n1 = read(lfd, buff+inbuf, BUFFERLEN-inbuf); 26390643Sbenno 26490643Sbenno debug(3, "read(K):%d\n", n1); 265159303Salc 266159303Salc if (n1 <= 0) { 267152180Sgrehan syslog(LOG_ERR, "read error (k-header): %m"); 268152180Sgrehan debug(1, "read error (k-header): %s\n", 269208990Salc STRERROR(errno)); 270152180Sgrehan return; 271152180Sgrehan } 27290643Sbenno 273152180Sgrehan left = 0; 274152180Sgrehan 275152180Sgrehan switch (do_kbuff(n1, buff, &left)) 276152180Sgrehan { 277152180Sgrehan case R_IO_ERROR : 278152180Sgrehan return; 279152180Sgrehan case R_MORE : 280152180Sgrehan inbuf += left; 281159303Salc break; 282159303Salc default : 283159627Sups inbuf = 0; 284152180Sgrehan break; 285152180Sgrehan } 286152180Sgrehan } 287152180Sgrehan 288214617Salc if (FD_ISSET(nfd, &rd)) { 289207155Salc n1 = recv(nfd, nbuff, sizeof(nbuff), 0); 290152180Sgrehan 291152180Sgrehan debug(3, "read(N):%d\n", n1); 292152180Sgrehan 293173708Salc if (n1 <= 0) { 294152180Sgrehan syslog(LOG_ERR, "read error (n-header): %m"); 295152180Sgrehan debug(1, "read error (n-header): %s\n", 296152180Sgrehan STRERROR(errno)); 297152180Sgrehan return; 298152180Sgrehan } 299152180Sgrehan 300152180Sgrehan switch (do_packet(n1, nbuff)) 301152180Sgrehan { 302160889Salc case R_IO_ERROR : 303152180Sgrehan return; 304152180Sgrehan default : 305152180Sgrehan break; 306152180Sgrehan } 307152180Sgrehan } 308190681Snwhitehorn } 309152180Sgrehan} 310152180Sgrehan 311213307Snwhitehorn 312152180Sgrehanint 313152180Sgrehanbuildsocket(nicname, sinp) 314213307Snwhitehorn char *nicname; 315152180Sgrehan struct sockaddr_in *sinp; 316213307Snwhitehorn{ 317152180Sgrehan struct sockaddr_in *reqip; 318198341Smarcel struct ifreq req; 319152180Sgrehan char opt; 320152180Sgrehan 321152180Sgrehan debug(2, "binding to %s:%s\n", nicname, inet_ntoa(sinp->sin_addr)); 322152180Sgrehan 323152180Sgrehan if (IN_MULTICAST(ntohl(sinp->sin_addr.s_addr))) { 324152180Sgrehan struct in_addr addr; 325152180Sgrehan struct ip_mreq mreq; 326159303Salc 327152180Sgrehan igmpfd = socket(AF_INET, SOCK_RAW, IPPROTO_IGMP); 328152180Sgrehan if (igmpfd == -1) { 329152180Sgrehan syslog(LOG_ERR, "socket:%m"); 330152180Sgrehan debug(1, "socket:%s\n", STRERROR(errno)); 331152180Sgrehan return -1; 332214617Salc } 333207155Salc 334152180Sgrehan bzero((char *)&req, sizeof(req)); 335152180Sgrehan strncpy(req.ifr_name, nicname, sizeof(req.ifr_name)); 336152180Sgrehan req.ifr_name[sizeof(req.ifr_name) - 1] = '\0'; 337173708Salc if (ioctl(igmpfd, SIOCGIFADDR, &req) == -1) { 338152180Sgrehan syslog(LOG_ERR, "ioctl(SIOCGIFADDR):%m"); 339152180Sgrehan debug(1, "ioctl(SIOCGIFADDR):%s\n", STRERROR(errno)); 340152180Sgrehan close(igmpfd); 341152180Sgrehan igmpfd = -1; 342152180Sgrehan return -1; 343152180Sgrehan } 344152180Sgrehan reqip = (struct sockaddr_in *)&req.ifr_addr; 345152180Sgrehan 346160889Salc addr = reqip->sin_addr; 347198341Smarcel if (setsockopt(igmpfd, IPPROTO_IP, IP_MULTICAST_IF, 348152180Sgrehan (char *)&addr, sizeof(addr)) == -1) { 349152180Sgrehan syslog(LOG_ERR, "setsockopt(IP_MULTICAST_IF(%s)):%m", 350152180Sgrehan inet_ntoa(addr)); 351152180Sgrehan debug(1, "setsockopt(IP_MULTICAST_IF(%s)):%s\n", 352152180Sgrehan inet_ntoa(addr), STRERROR(errno)); 353213307Snwhitehorn close(igmpfd); 354152180Sgrehan igmpfd = -1; 355152180Sgrehan return -1; 356152180Sgrehan } 357190681Snwhitehorn 358213307Snwhitehorn opt = 0; 359152180Sgrehan if (setsockopt(igmpfd, IPPROTO_IP, IP_MULTICAST_LOOP, 360152180Sgrehan (char *)&opt, sizeof(opt)) == -1) { 361152180Sgrehan syslog(LOG_ERR, "setsockopt(IP_MULTICAST_LOOP=0):%m"); 362152180Sgrehan debug(1, "setsockopt(IP_MULTICAST_LOOP=0):%s\n", 363213307Snwhitehorn STRERROR(errno)); 364152180Sgrehan close(igmpfd); 365152180Sgrehan igmpfd = -1; 366152180Sgrehan return -1; 367152180Sgrehan } 368152180Sgrehan 369212627Sgrehan opt = 63; 370152180Sgrehan if (setsockopt(igmpfd, IPPROTO_IP, IP_MULTICAST_TTL, 371213307Snwhitehorn (char *)&opt, sizeof(opt)) == -1) { 372213307Snwhitehorn syslog(LOG_ERR, "setsockopt(IP_MULTICAST_TTL=%d):%m", 373213307Snwhitehorn opt); 374213307Snwhitehorn debug(1, "setsockopt(IP_MULTICAST_TTL=%d):%s\n", opt, 375213307Snwhitehorn STRERROR(errno)); 376212627Sgrehan close(igmpfd); 377213307Snwhitehorn igmpfd = -1; 378213307Snwhitehorn return -1; 379213307Snwhitehorn } 380213307Snwhitehorn 381213307Snwhitehorn mreq.imr_multiaddr.s_addr = sinp->sin_addr.s_addr; 382213307Snwhitehorn mreq.imr_interface.s_addr = reqip->sin_addr.s_addr; 383213307Snwhitehorn 384213307Snwhitehorn if (setsockopt(igmpfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, 385213307Snwhitehorn (char *)&mreq, sizeof(mreq)) == -1) { 386213307Snwhitehorn char buffer[80]; 387213307Snwhitehorn 388213307Snwhitehorn sprintf(buffer, "%s,", inet_ntoa(sinp->sin_addr)); 389213307Snwhitehorn strcat(buffer, inet_ntoa(reqip->sin_addr)); 390213307Snwhitehorn 391213307Snwhitehorn syslog(LOG_ERR, 392213307Snwhitehorn "setsockpt(IP_ADD_MEMBERSHIP,%s):%m", buffer); 393213307Snwhitehorn debug(1, "setsockpt(IP_ADD_MEMBERSHIP,%s):%s\n", 394213307Snwhitehorn buffer, STRERROR(errno)); 395213307Snwhitehorn close(igmpfd); 396213307Snwhitehorn igmpfd = -1; 397213307Snwhitehorn return -1; 398213307Snwhitehorn } 399213307Snwhitehorn } 400213307Snwhitehorn nfd = socket(AF_INET, SOCK_DGRAM, 0); 401213307Snwhitehorn if (nfd == -1) { 402213307Snwhitehorn syslog(LOG_ERR, "socket:%m"); 403213307Snwhitehorn if (igmpfd != -1) { 404213307Snwhitehorn close(igmpfd); 405213307Snwhitehorn igmpfd = -1; 406183094Smarcel } 407183094Smarcel return -1; 408183094Smarcel } 409152180Sgrehan bzero((char *)&req, sizeof(req)); 410183094Smarcel strncpy(req.ifr_name, nicname, sizeof(req.ifr_name)); 411213407Snwhitehorn req.ifr_name[sizeof(req.ifr_name) - 1] = '\0'; 412183094Smarcel if (ioctl(nfd, SIOCGIFADDR, &req) == -1) { 413213407Snwhitehorn syslog(LOG_ERR, "ioctl(SIOCGIFADDR):%m"); 414183094Smarcel debug(1, "ioctl(SIOCGIFADDR):%s\n", STRERROR(errno)); 415183094Smarcel close(igmpfd); 416183094Smarcel igmpfd = -1; 417183094Smarcel return -1; 418183094Smarcel } 419183094Smarcel 420183094Smarcel if (bind(nfd, (struct sockaddr *)&req.ifr_addr, 421183094Smarcel sizeof(req.ifr_addr)) == -1) { 422183094Smarcel syslog(LOG_ERR, "bind:%m"); 423183094Smarcel debug(1, "bind:%s\n", STRERROR(errno)); 424183094Smarcel close(nfd); 425183094Smarcel if (igmpfd != -1) { 426183094Smarcel close(igmpfd); 427183094Smarcel igmpfd = -1; 428183094Smarcel } 429183094Smarcel nfd = -1; 43090643Sbenno return -1; 43190643Sbenno } 43277957Sbenno 43390643Sbenno if (connect(nfd, (struct sockaddr *)sinp, sizeof(*sinp)) == -1) { 43490643Sbenno syslog(LOG_ERR, "connect:%m"); 43577957Sbenno debug(1, "connect:%s\n", STRERROR(errno)); 43690643Sbenno close(nfd); 43790643Sbenno if (igmpfd != -1) { 43890643Sbenno close(igmpfd); 43990643Sbenno igmpfd = -1; 44090643Sbenno } 44190643Sbenno nfd = -1; 44290643Sbenno return -1; 443152180Sgrehan } 44477957Sbenno syslog(LOG_INFO, "Sending data to %s", inet_ntoa(sinp->sin_addr)); 44577957Sbenno debug(3, "Sending data to %s\n", inet_ntoa(sinp->sin_addr)); 44690643Sbenno 44790643Sbenno return nfd; 44890643Sbenno} 44990643Sbenno 45090643Sbenno 45190643Sbennoint 45290643Sbennodo_packet(pklen, buff) 45377957Sbenno int pklen; 454152180Sgrehan char *buff; 45577957Sbenno{ 45690643Sbenno synchdr_t *sh; 457159928Salc u_32_t magic; 45890643Sbenno int len; 45977957Sbenno int n2; 46077957Sbenno int n3; 46177957Sbenno 462152180Sgrehan while (pklen > 0) { 46377957Sbenno if (pklen < sizeof(*sh)) { 46477957Sbenno syslog(LOG_ERR, "packet length too short:%d", pklen); 46590643Sbenno debug(2, "packet length too short:%d\n", pklen); 46677957Sbenno return R_SKIP; 46777957Sbenno } 46890643Sbenno 469152180Sgrehan sh = (synchdr_t *)buff; 47090643Sbenno len = ntohl(sh->sm_len); 47190643Sbenno magic = ntohl(sh->sm_magic); 472159928Salc 47390643Sbenno if (magic != SYNHDRMAGIC) { 47490643Sbenno syslog(LOG_ERR, "invalid header magic %x", magic); 47590643Sbenno debug(2, "invalid header magic %x\n", magic); 47677957Sbenno return R_SKIP; 477152180Sgrehan } 47877957Sbenno 47990643Sbenno if (pklen < len + sizeof(*sh)) { 48090643Sbenno syslog(LOG_ERR, "packet length too short:%d", pklen); 48190643Sbenno debug(2, "packet length too short:%d\n", pklen); 48290643Sbenno return R_SKIP; 48377957Sbenno } 48477957Sbenno 48577957Sbenno if (debuglevel > 3) { 486152180Sgrehan printsynchdr(sh); 48777957Sbenno printcommand(sh->sm_cmd); 48890643Sbenno printtable(sh->sm_table); 48990643Sbenno printsmcproto(buff); 49090643Sbenno } 49190643Sbenno 49277957Sbenno n2 = sizeof(*sh) + len; 49390643Sbenno 494152180Sgrehan do { 49590643Sbenno n3 = write(lfd, buff, n2); 496159928Salc if (n3 <= 0) { 497159928Salc syslog(LOG_ERR, "write error: %m"); 498159928Salc debug(1, "write error: %s\n", STRERROR(errno)); 49990643Sbenno return R_IO_ERROR; 50090643Sbenno } 50190643Sbenno 50290643Sbenno n2 -= n3; 50390643Sbenno buff += n3; 50490643Sbenno pklen -= n3; 50590643Sbenno } while (n3 != 0); 50690643Sbenno } 50790643Sbenno 50877957Sbenno return R_OKAY; 50977957Sbenno} 51090643Sbenno 511152180Sgrehan 51277957Sbenno 51377957Sbennoint 514159928Salcdo_kbuff(inbuf, buf, left) 51590643Sbenno int inbuf, *left; 51677957Sbenno char *buf; 51777957Sbenno{ 51890643Sbenno synchdr_t *sh; 519152180Sgrehan u_32_t magic; 52077957Sbenno int complete; 52177957Sbenno int sendlen; 522159928Salc int error; 523159928Salc int bytes; 52490643Sbenno int len; 52590643Sbenno int n2; 52690643Sbenno int n3; 52790643Sbenno 528183094Smarcel sendlen = 0; 52977957Sbenno bytes = inbuf; 53077957Sbenno error = R_OKAY; 53190643Sbenno sh = (synchdr_t *)buf; 532152180Sgrehan 53377957Sbenno for (complete = 0; bytes > 0; complete++) { 53477957Sbenno len = ntohl(sh->sm_len); 535159928Salc magic = ntohl(sh->sm_magic); 53690643Sbenno 53790643Sbenno if (magic != SYNHDRMAGIC) { 53877957Sbenno syslog(LOG_ERR, 53990643Sbenno "read invalid header magic 0x%x, flushing", 54090643Sbenno magic); 54190643Sbenno debug(2, "read invalid header magic 0x%x, flushing\n", 54277957Sbenno magic); 54390643Sbenno n2 = SMC_RLOG; 544183094Smarcel (void) ioctl(lfd, SIOCIPFFL, &n2); 54590643Sbenno break; 546183094Smarcel } 547152180Sgrehan 54890643Sbenno if (debuglevel > 3) { 54977957Sbenno printsynchdr(sh); 55090643Sbenno printcommand(sh->sm_cmd); 551152180Sgrehan printtable(sh->sm_table); 55290643Sbenno putchar('\n'); 55390643Sbenno } 554159928Salc 55590643Sbenno if (bytes < sizeof(*sh) + len) { 55690643Sbenno debug(3, "Not enough bytes %d < %d\n", bytes, 55777957Sbenno sizeof(*sh) + len); 55890643Sbenno error = R_MORE; 55977957Sbenno break; 560183094Smarcel } 56177957Sbenno 56290643Sbenno if (debuglevel > 3) { 56390643Sbenno printsmcproto(buf); 56490643Sbenno } 56590643Sbenno 56677957Sbenno sendlen += len + sizeof(*sh); 567183094Smarcel sh = (synchdr_t *)(buf + sendlen); 56877957Sbenno bytes -= sendlen; 56990643Sbenno } 57090643Sbenno 57190643Sbenno if (complete) { 572152180Sgrehan n3 = send(nfd, buf, sendlen, 0); 573152180Sgrehan if (n3 <= 0) { 57477957Sbenno syslog(LOG_ERR, "write error: %m"); 57577957Sbenno debug(1, "write error: %s\n", STRERROR(errno)); 57690643Sbenno return R_IO_ERROR; 577152180Sgrehan } 57890643Sbenno debug(3, "send on %d len %d = %d\n", nfd, sendlen, n3); 57990643Sbenno error = R_OKAY; 58090643Sbenno } 58190643Sbenno 58290643Sbenno /* move buffer to the front,we might need to make 583152180Sgrehan * this more efficient, by using a rolling pointer 584152180Sgrehan * over the buffer and only copying it, when 58590643Sbenno * we are reaching the end 58690643Sbenno */ 58777957Sbenno if (bytes > 0) { 58890643Sbenno bcopy(buf + bytes, buf, bytes); 58977957Sbenno error = R_MORE; 59090643Sbenno } 59190643Sbenno debug(4, "complete %d bytes %d error %d\n", complete, bytes, error); 59290643Sbenno 59390643Sbenno *left = bytes; 59490643Sbenno 59590643Sbenno return error; 59690643Sbenno} 59790643Sbenno 59890643Sbenno 59990643Sbennovoid 60090643Sbennoprintcommand(cmd) 60190643Sbenno int cmd; 60290643Sbenno{ 60390643Sbenno 60490643Sbenno switch (cmd) 60590643Sbenno { 60677957Sbenno case SMC_CREATE : 60777957Sbenno printf(" cmd:CREATE"); 60877957Sbenno break; 609190681Snwhitehorn case SMC_UPDATE : 610178628Smarcel printf(" cmd:UPDATE"); 611178628Smarcel break; 612178628Smarcel default : 613178628Smarcel printf(" cmd:Unknown(%d)", cmd); 614178628Smarcel break; 615183094Smarcel } 616178628Smarcel} 617178628Smarcel 618178628Smarcel 619178628Smarcelvoid 620178628Smarcelprinttable(table) 621178628Smarcel int table; 622178628Smarcel{ 623178628Smarcel switch (table) 624178629Smarcel { 625178629Smarcel case SMC_NAT : 626178629Smarcel printf(" table:NAT"); 627178628Smarcel break; 628178629Smarcel case SMC_STATE : 629178629Smarcel printf(" table:STATE"); 630178629Smarcel break; 631178629Smarcel default : 632178629Smarcel printf(" table:Unknown(%d)", table); 633178628Smarcel break; 634178628Smarcel } 635178628Smarcel} 636215163Snwhitehorn 637183094Smarcel 638178628Smarcelvoid 639178628Smarcelprintsmcproto(buff) 640178628Smarcel char *buff; 641178628Smarcel{ 642178628Smarcel syncupdent_t *su; 643179254Smarcel synchdr_t *sh; 644178628Smarcel 645178628Smarcel sh = (synchdr_t *)buff; 646178628Smarcel 647152180Sgrehan if (sh->sm_cmd == SMC_CREATE) { 64877957Sbenno ; 64997346Sbenno 65090643Sbenno } else if (sh->sm_cmd == SMC_UPDATE) { 65190643Sbenno su = (syncupdent_t *)buff; 65290643Sbenno if (sh->sm_p == IPPROTO_TCP) { 653143200Sgrehan printf(" TCP Update: age %lu state %d/%d\n", 65490643Sbenno su->sup_tcp.stu_age, 655194784Sjeff su->sup_tcp.stu_state[0], 656209369Snwhitehorn su->sup_tcp.stu_state[1]); 65777957Sbenno } 65899037Sbenno } else { 659103604Sgrehan printf("Unknown command\n"); 66099037Sbenno } 66199037Sbenno} 66299037Sbenno 66399037Sbenno 66499037Sbennovoid 66599037Sbennoprintsynchdr(sh) 66699037Sbenno synchdr_t *sh; 66799037Sbenno{ 66899037Sbenno 66999037Sbenno printf("v:%d p:%d num:%d len:%d magic:%x", sh->sm_v, sh->sm_p, 67099037Sbenno ntohl(sh->sm_num), ntohl(sh->sm_len), ntohl(sh->sm_magic)); 67199037Sbenno} 67299037Sbenno