ipsyncs.c revision 145510
1145510Sdarrenr/* $NetBSD$ */ 2145510Sdarrenr 3145510Sdarrenr/* 4145510Sdarrenr * Copyright (C) 1993-2001 by Darren Reed. 5145510Sdarrenr * 6145510Sdarrenr * See the IPFILTER.LICENCE file for details on licencing. 7145510Sdarrenr */ 8145510Sdarrenr#if !defined(lint) 9145510Sdarrenrstatic const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed"; 10145510Sdarrenrstatic const char rcsid[] = "@(#)Id: ipsyncs.c,v 1.5.2.1 2004/10/31 18:46:44 darrenr Exp"; 11145510Sdarrenr#endif 12145510Sdarrenr#include <sys/types.h> 13145510Sdarrenr#include <sys/time.h> 14145510Sdarrenr#include <sys/socket.h> 15145510Sdarrenr 16145510Sdarrenr#include <netinet/in.h> 17145510Sdarrenr#include <net/if.h> 18145510Sdarrenr 19145510Sdarrenr#include <arpa/inet.h> 20145510Sdarrenr 21145510Sdarrenr#include <stdio.h> 22145510Sdarrenr#include <stdlib.h> 23145510Sdarrenr#include <fcntl.h> 24145510Sdarrenr#include <strings.h> 25145510Sdarrenr#include <unistd.h> 26145510Sdarrenr#include <syslog.h> 27145510Sdarrenr#include <errno.h> 28145510Sdarrenr#include <signal.h> 29145510Sdarrenr 30145510Sdarrenr#include "netinet/ip_compat.h" 31145510Sdarrenr#include "netinet/ip_fil.h" 32145510Sdarrenr#include "netinet/ip_state.h" 33145510Sdarrenr#include "netinet/ip_nat.h" 34145510Sdarrenr#include "netinet/ip_sync.h" 35145510Sdarrenr 36145510Sdarrenrint main __P((int, char *[])); 37145510Sdarrenr 38145510Sdarrenrint terminate = 0; 39145510Sdarrenr 40145510Sdarrenrvoid usage(const char *progname) { 41145510Sdarrenr fprintf(stderr, 42145510Sdarrenr "Usage: %s <destination IP> <destination port> [remote IP]\n", 43145510Sdarrenr progname); 44145510Sdarrenr} 45145510Sdarrenr 46145510Sdarrenrstatic void handleterm(int sig) 47145510Sdarrenr{ 48145510Sdarrenr terminate = sig; 49145510Sdarrenr 50145510Sdarrenr} 51145510Sdarrenr 52145510Sdarrenr#define BUFFERLEN 1400 53145510Sdarrenr 54145510Sdarrenrint main(argc, argv) 55145510Sdarrenrint argc; 56145510Sdarrenrchar *argv[]; 57145510Sdarrenr{ 58145510Sdarrenr int nfd = -1 , lfd = -1; 59145510Sdarrenr int n1, n2, n3, magic, len, inbuf; 60145510Sdarrenr struct sockaddr_in sin; 61145510Sdarrenr struct sockaddr_in in; 62145510Sdarrenr char buff[BUFFERLEN]; 63145510Sdarrenr synclogent_t *sl; 64145510Sdarrenr syncupdent_t *su; 65145510Sdarrenr synchdr_t *sh; 66145510Sdarrenr char *progname; 67145510Sdarrenr 68145510Sdarrenr progname = strrchr(argv[0], '/'); 69145510Sdarrenr if (progname) { 70145510Sdarrenr progname++; 71145510Sdarrenr } else { 72145510Sdarrenr progname = argv[0]; 73145510Sdarrenr } 74145510Sdarrenr 75145510Sdarrenr if (argc < 2) { 76145510Sdarrenr usage(progname); 77145510Sdarrenr exit(1); 78145510Sdarrenr } 79145510Sdarrenr 80145510Sdarrenr#if 0 81145510Sdarrenr signal(SIGHUP, handleterm); 82145510Sdarrenr signal(SIGINT, handleterm); 83145510Sdarrenr signal(SIGTERM, handleterm); 84145510Sdarrenr#endif 85145510Sdarrenr 86145510Sdarrenr openlog(progname, LOG_PID, LOG_SECURITY); 87145510Sdarrenr 88145510Sdarrenr lfd = open(IPSYNC_NAME, O_WRONLY); 89145510Sdarrenr if (lfd == -1) { 90145510Sdarrenr syslog(LOG_ERR, "Opening %s :%m", IPSYNC_NAME); 91145510Sdarrenr exit(1); 92145510Sdarrenr } 93145510Sdarrenr 94145510Sdarrenr bzero((char *)&sin, sizeof(sin)); 95145510Sdarrenr sin.sin_family = AF_INET; 96145510Sdarrenr if (argc > 1) 97145510Sdarrenr sin.sin_addr.s_addr = inet_addr(argv[1]); 98145510Sdarrenr if (argc > 2) 99145510Sdarrenr sin.sin_port = htons(atoi(argv[2])); 100145510Sdarrenr else 101145510Sdarrenr sin.sin_port = htons(43434); 102145510Sdarrenr if (argc > 3) 103145510Sdarrenr in.sin_addr.s_addr = inet_addr(argv[3]); 104145510Sdarrenr else 105145510Sdarrenr in.sin_addr.s_addr = 0; 106145510Sdarrenr in.sin_port = 0; 107145510Sdarrenr 108145510Sdarrenr while(1) { 109145510Sdarrenr 110145510Sdarrenr if (lfd != -1) 111145510Sdarrenr close(lfd); 112145510Sdarrenr if (nfd != -1) 113145510Sdarrenr close(nfd); 114145510Sdarrenr 115145510Sdarrenr lfd = open(IPSYNC_NAME, O_WRONLY); 116145510Sdarrenr if (lfd == -1) { 117145510Sdarrenr syslog(LOG_ERR, "Opening %s :%m", IPSYNC_NAME); 118145510Sdarrenr goto tryagain; 119145510Sdarrenr } 120145510Sdarrenr 121145510Sdarrenr nfd = socket(AF_INET, SOCK_DGRAM, 0); 122145510Sdarrenr if (nfd == -1) { 123145510Sdarrenr syslog(LOG_ERR, "Socket :%m"); 124145510Sdarrenr goto tryagain; 125145510Sdarrenr } 126145510Sdarrenr 127145510Sdarrenr n1 = 1; 128145510Sdarrenr setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, &n1, sizeof(n1)); 129145510Sdarrenr 130145510Sdarrenr if (bind(nfd, (struct sockaddr *)&sin, sizeof(sin)) == -1) { 131145510Sdarrenr syslog(LOG_ERR, "Bind: %m"); 132145510Sdarrenr goto tryagain; 133145510Sdarrenr } 134145510Sdarrenr 135145510Sdarrenr syslog(LOG_INFO, "Established connection to %s", 136145510Sdarrenr inet_ntoa(sin.sin_addr)); 137145510Sdarrenr 138145510Sdarrenr inbuf = 0; 139145510Sdarrenr while (1) { 140145510Sdarrenr 141145510Sdarrenr 142145510Sdarrenr /* 143145510Sdarrenr * XXX currently we do not check the source address 144145510Sdarrenr * of a datagram, this can be a security risk 145145510Sdarrenr */ 146145510Sdarrenr n1 = read(nfd, buff+inbuf, BUFFERLEN-inbuf); 147145510Sdarrenr 148145510Sdarrenr printf("header : %d bytes read (header = %d bytes)\n", 149145510Sdarrenr n1, sizeof(*sh)); 150145510Sdarrenr 151145510Sdarrenr if (n1 < 0) { 152145510Sdarrenr syslog(LOG_ERR, "Read error (header): %m"); 153145510Sdarrenr goto tryagain; 154145510Sdarrenr } 155145510Sdarrenr 156145510Sdarrenr if (n1 == 0) { 157145510Sdarrenr /* XXX can this happen??? */ 158145510Sdarrenr syslog(LOG_ERR, 159145510Sdarrenr "Read error (header) : No data"); 160145510Sdarrenr sleep(1); 161145510Sdarrenr continue; 162145510Sdarrenr } 163145510Sdarrenr 164145510Sdarrenr inbuf += n1; 165145510Sdarrenr 166145510Sdarrenrmoreinbuf: 167145510Sdarrenr if (inbuf < sizeof(*sh)) { 168145510Sdarrenr continue; /* need more data */ 169145510Sdarrenr } 170145510Sdarrenr 171145510Sdarrenr sh = (synchdr_t *)buff; 172145510Sdarrenr len = ntohl(sh->sm_len); 173145510Sdarrenr magic = ntohl(sh->sm_magic); 174145510Sdarrenr 175145510Sdarrenr if (magic != SYNHDRMAGIC) { 176145510Sdarrenr syslog(LOG_ERR, "Invalid header magic %x", 177145510Sdarrenr magic); 178145510Sdarrenr goto tryagain; 179145510Sdarrenr } 180145510Sdarrenr 181145510Sdarrenr#define IPSYNC_DEBUG 182145510Sdarrenr#ifdef IPSYNC_DEBUG 183145510Sdarrenr printf("v:%d p:%d len:%d magic:%x", sh->sm_v, 184145510Sdarrenr sh->sm_p, len, magic); 185145510Sdarrenr 186145510Sdarrenr if (sh->sm_cmd == SMC_CREATE) 187145510Sdarrenr printf(" cmd:CREATE"); 188145510Sdarrenr else if (sh->sm_cmd == SMC_UPDATE) 189145510Sdarrenr printf(" cmd:UPDATE"); 190145510Sdarrenr else 191145510Sdarrenr printf(" cmd:Unknown(%d)", sh->sm_cmd); 192145510Sdarrenr 193145510Sdarrenr if (sh->sm_table == SMC_NAT) 194145510Sdarrenr printf(" table:NAT"); 195145510Sdarrenr else if (sh->sm_table == SMC_STATE) 196145510Sdarrenr printf(" table:STATE"); 197145510Sdarrenr else 198145510Sdarrenr printf(" table:Unknown(%d)", sh->sm_table); 199145510Sdarrenr 200145510Sdarrenr printf(" num:%d\n", (u_32_t)ntohl(sh->sm_num)); 201145510Sdarrenr#endif 202145510Sdarrenr 203145510Sdarrenr if (inbuf < sizeof(*sh) + len) { 204145510Sdarrenr continue; /* need more data */ 205145510Sdarrenr goto tryagain; 206145510Sdarrenr } 207145510Sdarrenr 208145510Sdarrenr#ifdef IPSYNC_DEBUG 209145510Sdarrenr if (sh->sm_cmd == SMC_CREATE) { 210145510Sdarrenr sl = (synclogent_t *)buff; 211145510Sdarrenr 212145510Sdarrenr } else if (sh->sm_cmd == SMC_UPDATE) { 213145510Sdarrenr su = (syncupdent_t *)buff; 214145510Sdarrenr if (sh->sm_p == IPPROTO_TCP) { 215145510Sdarrenr printf(" TCP Update: age %lu state %d/%d\n", 216145510Sdarrenr su->sup_tcp.stu_age, 217145510Sdarrenr su->sup_tcp.stu_state[0], 218145510Sdarrenr su->sup_tcp.stu_state[1]); 219145510Sdarrenr } 220145510Sdarrenr } else { 221145510Sdarrenr printf("Unknown command\n"); 222145510Sdarrenr } 223145510Sdarrenr#endif 224145510Sdarrenr 225145510Sdarrenr n2 = sizeof(*sh) + len; 226145510Sdarrenr n3 = write(lfd, buff, n2); 227145510Sdarrenr if (n3 <= 0) { 228145510Sdarrenr syslog(LOG_ERR, "Write error: %m"); 229145510Sdarrenr goto tryagain; 230145510Sdarrenr } 231145510Sdarrenr 232145510Sdarrenr 233145510Sdarrenr if (n3 != n2) { 234145510Sdarrenr syslog(LOG_ERR, "Incomplete write (%d/%d)", 235145510Sdarrenr n3, n2); 236145510Sdarrenr goto tryagain; 237145510Sdarrenr } 238145510Sdarrenr 239145510Sdarrenr /* signal received? */ 240145510Sdarrenr if (terminate) 241145510Sdarrenr break; 242145510Sdarrenr 243145510Sdarrenr /* move buffer to the front,we might need to make 244145510Sdarrenr * this more efficient, by using a rolling pointer 245145510Sdarrenr * over the buffer and only copying it, when 246145510Sdarrenr * we are reaching the end 247145510Sdarrenr */ 248145510Sdarrenr inbuf -= n2; 249145510Sdarrenr if (inbuf) { 250145510Sdarrenr bcopy(buff+n2, buff, inbuf); 251145510Sdarrenr printf("More data in buffer\n"); 252145510Sdarrenr goto moreinbuf; 253145510Sdarrenr } 254145510Sdarrenr } 255145510Sdarrenr 256145510Sdarrenr if (terminate) 257145510Sdarrenr break; 258145510Sdarrenrtryagain: 259145510Sdarrenr sleep(1); 260145510Sdarrenr } 261145510Sdarrenr 262145510Sdarrenr 263145510Sdarrenr /* terminate */ 264145510Sdarrenr if (lfd != -1) 265145510Sdarrenr close(lfd); 266145510Sdarrenr if (nfd != -1) 267145510Sdarrenr close(nfd); 268145510Sdarrenr 269145510Sdarrenr syslog(LOG_ERR, "signal %d received, exiting...", terminate); 270145510Sdarrenr 271145510Sdarrenr exit(1); 272145510Sdarrenr} 273