ipsyncs.c revision 145519
1/* $FreeBSD: head/contrib/ipfilter/tools/ipsyncs.c 145519 2005-04-25 18:20:15Z darrenr $ */ 2 3/* 4 * Copyright (C) 1993-2001 by Darren Reed. 5 * 6 * See the IPFILTER.LICENCE file for details on licencing. 7 */ 8#if !defined(lint) 9static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed"; 10static const char rcsid[] = "@(#)Id: ipsyncs.c,v 1.5.2.1 2004/10/31 18:46:44 darrenr Exp"; 11#endif 12#include <sys/types.h> 13#include <sys/time.h> 14#include <sys/socket.h> 15 16#include <netinet/in.h> 17#include <net/if.h> 18 19#include <arpa/inet.h> 20 21#include <stdio.h> 22#include <stdlib.h> 23#include <fcntl.h> 24#include <strings.h> 25#include <unistd.h> 26#include <syslog.h> 27#include <errno.h> 28#include <signal.h> 29 30#include "netinet/ip_compat.h" 31#include "netinet/ip_fil.h" 32#include "netinet/ip_state.h" 33#include "netinet/ip_nat.h" 34#include "netinet/ip_sync.h" 35 36int main __P((int, char *[])); 37 38int terminate = 0; 39 40void usage(const char *progname) { 41 fprintf(stderr, 42 "Usage: %s <destination IP> <destination port> [remote IP]\n", 43 progname); 44} 45 46static void handleterm(int sig) 47{ 48 terminate = sig; 49 50} 51 52#define BUFFERLEN 1400 53 54int main(argc, argv) 55int argc; 56char *argv[]; 57{ 58 int nfd = -1 , lfd = -1; 59 int n1, n2, n3, magic, len, inbuf; 60 struct sockaddr_in sin; 61 struct sockaddr_in in; 62 char buff[BUFFERLEN]; 63 synclogent_t *sl; 64 syncupdent_t *su; 65 synchdr_t *sh; 66 char *progname; 67 68 progname = strrchr(argv[0], '/'); 69 if (progname) { 70 progname++; 71 } else { 72 progname = argv[0]; 73 } 74 75 if (argc < 2) { 76 usage(progname); 77 exit(1); 78 } 79 80#if 0 81 signal(SIGHUP, handleterm); 82 signal(SIGINT, handleterm); 83 signal(SIGTERM, handleterm); 84#endif 85 86 openlog(progname, LOG_PID, LOG_SECURITY); 87 88 lfd = open(IPSYNC_NAME, O_WRONLY); 89 if (lfd == -1) { 90 syslog(LOG_ERR, "Opening %s :%m", IPSYNC_NAME); 91 exit(1); 92 } 93 94 bzero((char *)&sin, sizeof(sin)); 95 sin.sin_family = AF_INET; 96 if (argc > 1) 97 sin.sin_addr.s_addr = inet_addr(argv[1]); 98 if (argc > 2) 99 sin.sin_port = htons(atoi(argv[2])); 100 else 101 sin.sin_port = htons(43434); 102 if (argc > 3) 103 in.sin_addr.s_addr = inet_addr(argv[3]); 104 else 105 in.sin_addr.s_addr = 0; 106 in.sin_port = 0; 107 108 while(1) { 109 110 if (lfd != -1) 111 close(lfd); 112 if (nfd != -1) 113 close(nfd); 114 115 lfd = open(IPSYNC_NAME, O_WRONLY); 116 if (lfd == -1) { 117 syslog(LOG_ERR, "Opening %s :%m", IPSYNC_NAME); 118 goto tryagain; 119 } 120 121 nfd = socket(AF_INET, SOCK_DGRAM, 0); 122 if (nfd == -1) { 123 syslog(LOG_ERR, "Socket :%m"); 124 goto tryagain; 125 } 126 127 n1 = 1; 128 setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, &n1, sizeof(n1)); 129 130 if (bind(nfd, (struct sockaddr *)&sin, sizeof(sin)) == -1) { 131 syslog(LOG_ERR, "Bind: %m"); 132 goto tryagain; 133 } 134 135 syslog(LOG_INFO, "Established connection to %s", 136 inet_ntoa(sin.sin_addr)); 137 138 inbuf = 0; 139 while (1) { 140 141 142 /* 143 * XXX currently we do not check the source address 144 * of a datagram, this can be a security risk 145 */ 146 n1 = read(nfd, buff+inbuf, BUFFERLEN-inbuf); 147 148 printf("header : %d bytes read (header = %d bytes)\n", 149 n1, sizeof(*sh)); 150 151 if (n1 < 0) { 152 syslog(LOG_ERR, "Read error (header): %m"); 153 goto tryagain; 154 } 155 156 if (n1 == 0) { 157 /* XXX can this happen??? */ 158 syslog(LOG_ERR, 159 "Read error (header) : No data"); 160 sleep(1); 161 continue; 162 } 163 164 inbuf += n1; 165 166moreinbuf: 167 if (inbuf < sizeof(*sh)) { 168 continue; /* need more data */ 169 } 170 171 sh = (synchdr_t *)buff; 172 len = ntohl(sh->sm_len); 173 magic = ntohl(sh->sm_magic); 174 175 if (magic != SYNHDRMAGIC) { 176 syslog(LOG_ERR, "Invalid header magic %x", 177 magic); 178 goto tryagain; 179 } 180 181#define IPSYNC_DEBUG 182#ifdef IPSYNC_DEBUG 183 printf("v:%d p:%d len:%d magic:%x", sh->sm_v, 184 sh->sm_p, len, magic); 185 186 if (sh->sm_cmd == SMC_CREATE) 187 printf(" cmd:CREATE"); 188 else if (sh->sm_cmd == SMC_UPDATE) 189 printf(" cmd:UPDATE"); 190 else 191 printf(" cmd:Unknown(%d)", sh->sm_cmd); 192 193 if (sh->sm_table == SMC_NAT) 194 printf(" table:NAT"); 195 else if (sh->sm_table == SMC_STATE) 196 printf(" table:STATE"); 197 else 198 printf(" table:Unknown(%d)", sh->sm_table); 199 200 printf(" num:%d\n", (u_32_t)ntohl(sh->sm_num)); 201#endif 202 203 if (inbuf < sizeof(*sh) + len) { 204 continue; /* need more data */ 205 goto tryagain; 206 } 207 208#ifdef IPSYNC_DEBUG 209 if (sh->sm_cmd == SMC_CREATE) { 210 sl = (synclogent_t *)buff; 211 212 } else if (sh->sm_cmd == SMC_UPDATE) { 213 su = (syncupdent_t *)buff; 214 if (sh->sm_p == IPPROTO_TCP) { 215 printf(" TCP Update: age %lu state %d/%d\n", 216 su->sup_tcp.stu_age, 217 su->sup_tcp.stu_state[0], 218 su->sup_tcp.stu_state[1]); 219 } 220 } else { 221 printf("Unknown command\n"); 222 } 223#endif 224 225 n2 = sizeof(*sh) + len; 226 n3 = write(lfd, buff, n2); 227 if (n3 <= 0) { 228 syslog(LOG_ERR, "Write error: %m"); 229 goto tryagain; 230 } 231 232 233 if (n3 != n2) { 234 syslog(LOG_ERR, "Incomplete write (%d/%d)", 235 n3, n2); 236 goto tryagain; 237 } 238 239 /* signal received? */ 240 if (terminate) 241 break; 242 243 /* move buffer to the front,we might need to make 244 * this more efficient, by using a rolling pointer 245 * over the buffer and only copying it, when 246 * we are reaching the end 247 */ 248 inbuf -= n2; 249 if (inbuf) { 250 bcopy(buff+n2, buff, inbuf); 251 printf("More data in buffer\n"); 252 goto moreinbuf; 253 } 254 } 255 256 if (terminate) 257 break; 258tryagain: 259 sleep(1); 260 } 261 262 263 /* terminate */ 264 if (lfd != -1) 265 close(lfd); 266 if (nfd != -1) 267 close(nfd); 268 269 syslog(LOG_ERR, "signal %d received, exiting...", terminate); 270 271 exit(1); 272} 273