1193326Sed 2193326Sed/* 3193326Sed * Copyright (C) 2012 by Darren Reed. 4193326Sed * 5193326Sed * See the IPFILTER.LICENCE file for details on licencing. 6193326Sed */ 7193326Sed#include <sys/types.h> 8193326Sed#include <sys/time.h> 9193326Sed#include <sys/socket.h> 10193326Sed 11193326Sed#include <netinet/in.h> 12193326Sed#include <net/if.h> 13193326Sed 14193326Sed#include <arpa/inet.h> 15193326Sed 16193326Sed#include <stdio.h> 17226890Sdim#include <stdlib.h> 18252723Sdim#include <fcntl.h> 19218893Sdim#include <unistd.h> 20193326Sed#include <string.h> 21193326Sed#include <syslog.h> 22193326Sed#include <signal.h> 23226890Sdim 24226890Sdim#include "netinet/ip_compat.h" 25226890Sdim#include "netinet/ip_fil.h" 26226890Sdim#include "netinet/ip_nat.h" 27218893Sdim#include "netinet/ip_state.h" 28226890Sdim#include "netinet/ip_sync.h" 29193326Sed 30226890Sdim 31226890Sdimint main(int, char *[]); 32226890Sdimvoid usage(const char *); 33226890Sdim 34226890Sdimint terminate = 0; 35226890Sdim 36226890Sdimvoid usage(const char *progname) { 37226890Sdim fprintf(stderr, "Usage: %s <destination IP> <destination port>\n", progname); 38226890Sdim} 39226890Sdim 40226890Sdim#if 0 41226890Sdimstatic void handleterm(int sig) 42193326Sed{ 43193326Sed terminate = sig; 44193326Sed} 45193326Sed#endif 46193326Sed 47193326Sed 48193326Sed/* should be large enough to hold header + any datatype */ 49193326Sed#define BUFFERLEN 1400 50193326Sed 51210299Sedint main(argc, argv) 52210299Sed int argc; 53193326Sed char *argv[]; 54193326Sed{ 55193326Sed struct sockaddr_in sin; 56193326Sed char buff[BUFFERLEN]; 57193326Sed synclogent_t *sl; 58200583Srdivacky syncupdent_t *su; 59200583Srdivacky int nfd = -1, lfd = -1, n1, n2, n3, len; 60200583Srdivacky int inbuf; 61193326Sed u_32_t magic; 62193326Sed synchdr_t *sh; 63235633Sdim char *progname; 64198092Srdivacky 65224145Sdim progname = strrchr(argv[0], '/'); 66224145Sdim if (progname) { 67224145Sdim progname++; 68226890Sdim } else { 69252723Sdim progname = argv[0]; 70252723Sdim } 71252723Sdim 72252723Sdim 73252723Sdim if (argc < 2) { 74252723Sdim usage(progname); 75219077Sdim exit(1); 76219077Sdim } 77219077Sdim 78219077Sdim#if 0 79219077Sdim signal(SIGHUP, handleterm); 80219077Sdim signal(SIGINT, handleterm); 81219077Sdim signal(SIGTERM, handleterm); 82219077Sdim#endif 83219077Sdim 84219077Sdim openlog(progname, LOG_PID, LOG_SECURITY); 85226890Sdim 86226890Sdim bzero((char *)&sin, sizeof(sin)); 87226890Sdim sin.sin_family = AF_INET; 88226890Sdim sin.sin_addr.s_addr = inet_addr(argv[1]); 89226890Sdim if (argc > 2) 90226890Sdim sin.sin_port = htons(atoi(argv[2])); 91226890Sdim else 92226890Sdim sin.sin_port = htons(43434); 93226890Sdim 94226890Sdim while (1) { 95226890Sdim 96226890Sdim if (lfd != -1) 97226890Sdim close(lfd); 98226890Sdim if (nfd != -1) 99226890Sdim close(nfd); 100226890Sdim 101226890Sdim lfd = open(IPSYNC_NAME, O_RDONLY); 102226890Sdim if (lfd == -1) { 103226890Sdim syslog(LOG_ERR, "Opening %s :%m", IPSYNC_NAME); 104226890Sdim goto tryagain; 105226890Sdim } 106226890Sdim 107226890Sdim nfd = socket(AF_INET, SOCK_DGRAM, 0); 108226890Sdim if (nfd == -1) { 109226890Sdim syslog(LOG_ERR, "Socket :%m"); 110226890Sdim goto tryagain; 111226890Sdim } 112226890Sdim 113226890Sdim if (connect(nfd, (struct sockaddr *)&sin, sizeof(sin)) == -1) { 114226890Sdim syslog(LOG_ERR, "Connect: %m"); 115226890Sdim goto tryagain; 116226890Sdim } 117226890Sdim 118226890Sdim syslog(LOG_INFO, "Sending data to %s", 119226890Sdim inet_ntoa(sin.sin_addr)); 120226890Sdim 121226890Sdim inbuf = 0; 122226890Sdim while (1) { 123226890Sdim 124226890Sdim n1 = read(lfd, buff+inbuf, BUFFERLEN-inbuf); 125226890Sdim 126226890Sdim printf("header : %d bytes read (header = %d bytes)\n", 127226890Sdim n1, (int) sizeof(*sh)); 128226890Sdim 129226890Sdim if (n1 < 0) { 130226890Sdim syslog(LOG_ERR, "Read error (header): %m"); 131226890Sdim goto tryagain; 132226890Sdim } 133226890Sdim 134226890Sdim if (n1 == 0) { 135226890Sdim /* XXX can this happen??? */ 136226890Sdim syslog(LOG_ERR, 137226890Sdim "Read error (header) : No data"); 138226890Sdim sleep(1); 139252723Sdim continue; 140226890Sdim } 141226890Sdim 142226890Sdim inbuf += n1; 143226890Sdim 144226890Sdimmoreinbuf: 145226890Sdim if (inbuf < sizeof(*sh)) { 146226890Sdim continue; /* need more data */ 147226890Sdim } 148226890Sdim 149226890Sdim sh = (synchdr_t *)buff; 150226890Sdim len = ntohl(sh->sm_len); 151226890Sdim magic = ntohl(sh->sm_magic); 152226890Sdim 153226890Sdim if (magic != SYNHDRMAGIC) { 154226890Sdim syslog(LOG_ERR, 155226890Sdim "Invalid header magic %x", magic); 156226890Sdim goto tryagain; 157226890Sdim } 158226890Sdim 159226890Sdim#define IPSYNC_DEBUG 160226890Sdim#ifdef IPSYNC_DEBUG 161226890Sdim printf("v:%d p:%d len:%d magic:%x", sh->sm_v, 162226890Sdim sh->sm_p, len, magic); 163226890Sdim 164226890Sdim if (sh->sm_cmd == SMC_CREATE) 165226890Sdim printf(" cmd:CREATE"); 166226890Sdim else if (sh->sm_cmd == SMC_UPDATE) 167226890Sdim printf(" cmd:UPDATE"); 168226890Sdim else 169226890Sdim printf(" cmd:Unknown(%d)", sh->sm_cmd); 170226890Sdim 171226890Sdim if (sh->sm_table == SMC_NAT) 172226890Sdim printf(" table:NAT"); 173226890Sdim else if (sh->sm_table == SMC_STATE) 174226890Sdim printf(" table:STATE"); 175226890Sdim else 176226890Sdim printf(" table:Unknown(%d)", sh->sm_table); 177226890Sdim 178226890Sdim printf(" num:%d\n", (u_32_t)ntohl(sh->sm_num)); 179226890Sdim#endif 180193326Sed 181198092Srdivacky if (inbuf < sizeof(*sh) + len) { 182193326Sed continue; /* need more data */ 183193326Sed goto tryagain; 184226890Sdim } 185193326Sed 186193326Sed#ifdef IPSYNC_DEBUG 187193326Sed if (sh->sm_cmd == SMC_CREATE) { 188193326Sed sl = (synclogent_t *)buff; 189 190 } else if (sh->sm_cmd == SMC_UPDATE) { 191 su = (syncupdent_t *)buff; 192 if (sh->sm_p == IPPROTO_TCP) { 193 printf(" TCP Update: age %lu state %d/%d\n", 194 su->sup_tcp.stu_age, 195 su->sup_tcp.stu_state[0], 196 su->sup_tcp.stu_state[1]); 197 } 198 } else { 199 printf("Unknown command\n"); 200 } 201#endif 202 203 n2 = sizeof(*sh) + len; 204 n3 = write(nfd, buff, n2); 205 if (n3 <= 0) { 206 syslog(LOG_ERR, "Write error: %m"); 207 goto tryagain; 208 } 209 210 211 if (n3 != n2) { 212 syslog(LOG_ERR, "Incomplete write (%d/%d)", 213 n3, n2); 214 goto tryagain; 215 } 216 217 /* signal received? */ 218 if (terminate) 219 break; 220 221 /* move buffer to the front,we might need to make 222 * this more efficient, by using a rolling pointer 223 * over the buffer and only copying it, when 224 * we are reaching the end 225 */ 226 inbuf -= n2; 227 if (inbuf) { 228 bcopy(buff+n2, buff, inbuf); 229 printf("More data in buffer\n"); 230 goto moreinbuf; 231 } 232 } 233 234 if (terminate) 235 break; 236tryagain: 237 sleep(1); 238 } 239 240 241 /* terminate */ 242 if (lfd != -1) 243 close(lfd); 244 if (nfd != -1) 245 close(nfd); 246 247 syslog(LOG_ERR, "signal %d received, exiting...", terminate); 248 249 exit(1); 250} 251 252