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