1 2 /* 3 * Copyright (C) 2012 by Darren Reed. 4 * 5 * See the IPFILTER.LICENCE file for details on licencing. 6 */ 7 #include <sys/types.h> 8 #include <sys/time.h> 9 #include <sys/socket.h> 10 11 #include <netinet/in.h> 12 #include <net/if.h> 13 14 #include <arpa/inet.h> 15 16 #include <stdio.h> 17 #include <stdlib.h> 18 #include <fcntl.h> 19 #include <unistd.h> 20 #include <string.h> 21 #include <syslog.h> 22 #include <signal.h> 23 24 #include "netinet/ip_compat.h" 25 #include "netinet/ip_fil.h" 26 #include "netinet/ip_nat.h" 27 #include "netinet/ip_state.h" 28 #include "netinet/ip_sync.h" 29 30 31 int main(int, char *[]); 32 void usage(const char *); 33 34 int terminate = 0; 35 36 void usage(const char *progname) { 37 fprintf(stderr, "Usage: %s <destination IP> <destination port>\n", progname); 38 } 39 40 #if 0 41 static void handleterm(int sig) 42 { 43 terminate = sig; 44 } 45 #endif 46 47 48 /* should be large enough to hold header + any datatype */ 49 #define BUFFERLEN 1400 50 51 int main(argc, argv) 52 int argc; 53 char *argv[]; 54 { 55 struct sockaddr_in sin; 56 char buff[BUFFERLEN]; 57 synclogent_t *sl; 58 syncupdent_t *su; 59 int nfd = -1, lfd = -1, n1, n2, n3, len; 60 int inbuf; 61 u_32_t magic; 62 synchdr_t *sh; 63 char *progname; 64 65 progname = strrchr(argv[0], '/'); 66 if (progname) { 67 progname++; 68 } else { 69 progname = argv[0]; 70 } 71 72 73 if (argc < 2) { 74 usage(progname); 75 exit(1); 76 } 77 78 #if 0 79 signal(SIGHUP, handleterm); 80 signal(SIGINT, handleterm); 81 signal(SIGTERM, handleterm); 82 #endif 83 84 openlog(progname, LOG_PID, LOG_SECURITY); 85 86 bzero((char *)&sin, sizeof(sin)); 87 sin.sin_family = AF_INET; 88 sin.sin_addr.s_addr = inet_addr(argv[1]); 89 if (argc > 2) 90 sin.sin_port = htons(atoi(argv[2])); 91 else 92 sin.sin_port = htons(43434); 93 94 while (1) { 95 96 if (lfd != -1) 97 close(lfd); 98 if (nfd != -1) 99 close(nfd); 100 101 lfd = open(IPSYNC_NAME, O_RDONLY); 102 if (lfd == -1) { 103 syslog(LOG_ERR, "Opening %s :%m", IPSYNC_NAME); 104 goto tryagain; 105 } 106 107 nfd = socket(AF_INET, SOCK_DGRAM, 0); 108 if (nfd == -1) { 109 syslog(LOG_ERR, "Socket :%m"); 110 goto tryagain; 111 } 112 113 if (connect(nfd, (struct sockaddr *)&sin, sizeof(sin)) == -1) { 114 syslog(LOG_ERR, "Connect: %m"); 115 goto tryagain; 116 } 117 118 syslog(LOG_INFO, "Sending data to %s", 119 inet_ntoa(sin.sin_addr)); 120 121 inbuf = 0; 122 while (1) { 123 124 n1 = read(lfd, buff+inbuf, BUFFERLEN-inbuf); 125 126 printf("header : %d bytes read (header = %d bytes)\n", 127 n1, (int) sizeof(*sh)); 128 129 if (n1 < 0) { 130 syslog(LOG_ERR, "Read error (header): %m"); 131 goto tryagain; 132 } 133 134 if (n1 == 0) { 135 /* XXX can this happen??? */ 136 syslog(LOG_ERR, 137 "Read error (header) : No data"); 138 sleep(1); 139 continue; 140 } 141 142 inbuf += n1; 143 144 moreinbuf: 145 if (inbuf < sizeof(*sh)) { 146 continue; /* need more data */ 147 } 148 149 sh = (synchdr_t *)buff; 150 len = ntohl(sh->sm_len); 151 magic = ntohl(sh->sm_magic); 152 153 if (magic != SYNHDRMAGIC) { 154 syslog(LOG_ERR, 155 "Invalid header magic %x", magic); 156 goto tryagain; 157 } 158 159 #define IPSYNC_DEBUG 160 #ifdef IPSYNC_DEBUG 161 printf("v:%d p:%d len:%d magic:%x", sh->sm_v, 162 sh->sm_p, len, magic); 163 164 if (sh->sm_cmd == SMC_CREATE) 165 printf(" cmd:CREATE"); 166 else if (sh->sm_cmd == SMC_UPDATE) 167 printf(" cmd:UPDATE"); 168 else 169 printf(" cmd:Unknown(%d)", sh->sm_cmd); 170 171 if (sh->sm_table == SMC_NAT) 172 printf(" table:NAT"); 173 else if (sh->sm_table == SMC_STATE) 174 printf(" table:STATE"); 175 else 176 printf(" table:Unknown(%d)", sh->sm_table); 177 178 printf(" num:%d\n", (u_32_t)ntohl(sh->sm_num)); 179 #endif 180 181 if (inbuf < sizeof(*sh) + len) { 182 continue; /* need more data */ 183 goto tryagain; 184 } 185 186 #ifdef IPSYNC_DEBUG 187 if (sh->sm_cmd == SMC_CREATE) { 188 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; 236 tryagain: 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