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