00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #if 0
00033
00034 #ifndef lint
00035 static char copyright[] =
00036 "@(#) Copyright (c) 2002-2004\n\
00037 Netherlands Forensic Institute. All rights reserved.\n";
00038 #endif
00039 #endif
00040
00041 #ifdef HAVE_CONFIG_H
00042 #include <config.h>
00043 #endif
00044
00045 #include <stdarg.h>
00046 #include <sys/types.h>
00047 #include <netdb.h>
00048 #include <netinet/in.h>
00049 #include <arpa/inet.h>
00050 #include <sys/socket.h>
00051 #include <string.h>
00052 #include <signal.h>
00053 #include <stdlib.h>
00054 #include <stdio.h>
00055 #include <sys/un.h>
00056
00057 #include "rdd.h"
00058 #include "writer.h"
00059
00060
00061
00062 static int tcp_write(RDD_WRITER *w, const unsigned char *buf, unsigned nbyte);
00063 static int tcp_close(RDD_WRITER *w);
00064 static int tcp_compare_address(RDD_WRITER *w, struct addrinfo *address, int *result);
00065
00066 static RDD_WRITE_OPS tcp_write_ops = {
00067 tcp_write,
00068 tcp_close,
00069 tcp_compare_address
00070 };
00071
00072 typedef struct _RDD_TCP_WRITER {
00073 struct addrinfo *address;
00074 RDD_WRITER *parent;
00075 } RDD_TCP_WRITER;
00076
00077 static int
00078 create_tcp_writer(RDD_WRITER **self)
00079 {
00080 RDD_WRITER *w = 0;
00081 int rc;
00082
00083 if (self == 0) {
00084 return RDD_BADARG;
00085 }
00086
00087 rc = rdd_new_writer(&w, &tcp_write_ops, sizeof(RDD_TCP_WRITER));
00088 if (rc != RDD_OK) {
00089 return rc;
00090 }
00091 RDD_TCP_WRITER *state = w->state;
00092 state->parent = 0;
00093 state->address = 0;
00094
00095 *self = w;
00096 return RDD_OK;
00097 }
00098
00099
00100 int
00101 rdd_get_address(const char *host, unsigned int port, struct addrinfo ** addr)
00102 {
00103 struct addrinfo info;
00104 char service_name[16];
00105
00106 if (host == 0 || strlen(host) == 0) {
00107 return RDD_BADARG;
00108 }
00109 if (addr == 0) {
00110 return RDD_BADARG;
00111 }
00112
00113 memset((char *)&info, '\000', sizeof(struct addrinfo));
00114 info.ai_socktype = SOCK_STREAM;
00115
00116 if (snprintf(service_name, sizeof(service_name), "%u", port) >= sizeof(service_name)) {
00117 return RDD_BADARG;
00118 }
00119
00120 if (getaddrinfo(host, service_name, &info, addr) != 0) {
00121 return RDD_ECONNECT;
00122 }
00123
00124 return RDD_OK;
00125
00126
00127 }
00128
00129 static int
00130 set_writer_address(RDD_WRITER *w, struct addrinfo * addr)
00131 {
00132 if (w == 0) {
00133 return RDD_BADARG;
00134 }
00135 RDD_TCP_WRITER *state = w->state;
00136
00137 state->address = addr;
00138
00139 return RDD_OK;
00140 }
00141
00142 static int
00143 connect_tcp_writer(RDD_WRITER *w)
00144 {
00145 int sock = -1;
00146 int rc;
00147
00148 RDD_TCP_WRITER *state = w->state;
00149
00150 struct addrinfo * addr = state->address;
00151
00152 if ((sock = socket(addr->ai_family, SOCK_STREAM, 0)) < 0) {
00153 return RDD_ECONNECT;
00154 }
00155
00156 if (connect(sock, addr->ai_addr, addr->ai_addrlen) < 0) {
00157 return RDD_ECONNECT;
00158 }
00159
00160 rc = rdd_open_fd_writer(&state->parent, sock);
00161 if (rc != RDD_OK) {
00162 return rc;
00163 }
00164 return RDD_OK;
00165 }
00166
00167 int
00168 rdd_open_tcp_writer(RDD_WRITER **self, const char *host, unsigned int port)
00169 {
00170 int rc;
00171 rc = create_tcp_writer(self);
00172 if (rc != RDD_OK) {
00173 return rc;
00174 }
00175 struct addrinfo *address;
00176
00177 rc = rdd_get_address(host, port, &address);
00178 if (rc != RDD_OK) {
00179 goto error;
00180 }
00181
00182 rc = set_writer_address(*self, address);
00183 if (rc != RDD_OK) {
00184 goto error;
00185 }
00186
00187 rc = connect_tcp_writer(*self);
00188 if (rc != RDD_OK) {
00189 goto error;
00190 }
00191 return RDD_OK;
00192
00193 error:
00194 rdd_writer_close(*self);
00195 return rc;
00196 }
00197
00198 static int
00199 tcp_write(RDD_WRITER *w, const unsigned char *buf, unsigned nbyte)
00200 {
00201 if (w == 0) {
00202 return RDD_BADARG;
00203 }
00204 RDD_TCP_WRITER *state = w->state;
00205
00206 if (state->parent == 0) {
00207 return RDD_EWRITE;
00208 }
00209 return rdd_writer_write(state->parent, buf, nbyte);
00210 }
00211
00212 static int
00213 tcp_close(RDD_WRITER *self)
00214 {
00215 RDD_TCP_WRITER *state = self->state;
00216 int rc;
00217
00218 if (state->parent != 0) {
00219 if ((rc = rdd_writer_close(state->parent)) != RDD_OK) {
00220 return rc;
00221 }
00222 }
00223
00224 if (state->address != 0) {
00225 freeaddrinfo(state->address);
00226 }
00227
00228 return RDD_OK;
00229 }
00230
00231 static int
00232 compare_sockaddr_un(struct sockaddr_un * address1, struct sockaddr_un * address2)
00233 {
00234 if (address1 == 0) {
00235 return (address2 == 0);
00236 }
00237 if (address2 == 0) {
00238 return 0;
00239 }
00240
00241 if (address1->sun_family != address2->sun_family) {
00242 return 0;
00243 }
00244 return !strcmp(address1->sun_path, address2->sun_path);
00245 }
00246
00247 static int
00248 compare_sockaddr_in(struct sockaddr_in * address1, struct sockaddr_in * address2)
00249 {
00250 if (address1 == 0) {
00251 return (address2 == 0);
00252 }
00253 if (address2 == 0) {
00254 return 0;
00255 }
00256
00257 if (address1->sin_family != address2->sin_family) {
00258 return 0;
00259 }
00260
00261 if (address1->sin_addr.s_addr != address2->sin_addr.s_addr) {
00262 return 0;
00263 }
00264 return address1->sin_port == address2->sin_port;
00265 }
00266
00267 static int
00268 compare_sockaddr_in6(struct sockaddr_in6 * address1, struct sockaddr_in6 * address2)
00269 {
00270 if (address1 == 0) {
00271 return (address2 == 0);
00272 }
00273 if (address2 == 0) {
00274 return 0;
00275 }
00276
00277 if (address1->sin6_family != address2->sin6_family) {
00278 return 0;
00279 }
00280
00281 if (memcmp(address1->sin6_addr.s6_addr, address2->sin6_addr.s6_addr, sizeof(address1->sin6_addr.s6_addr))) {
00282 return 0;
00283 }
00284
00285 return address1->sin6_port == address2->sin6_port;
00286 }
00287
00288
00289 static int
00290 compare_sockaddr(struct sockaddr * address1, struct sockaddr * address2)
00291 {
00292 if (address1 == 0) {
00293 return (address2 == 0);
00294 }
00295 if (address2 == 0) {
00296 return 0;
00297 }
00298 if (address1->sa_family != address2->sa_family) {
00299 return 0;
00300 }
00301 switch(address1->sa_family) {
00302 case PF_LOCAL:
00303 return compare_sockaddr_un((struct sockaddr_un *)address1, (struct sockaddr_un *)address2);
00304 break;
00305 case AF_INET:
00306 return compare_sockaddr_in((struct sockaddr_in *)address1, (struct sockaddr_in *)address2);
00307 case AF_INET6:
00308 return compare_sockaddr_in6((struct sockaddr_in6 *)address1, (struct sockaddr_in6 *)address2);
00309 break;
00310 case AF_UNSPEC:
00311 default:
00312 return 0;
00313 break;
00314
00315 }
00316 }
00317
00318 static int
00319 compare_writer_address(RDD_WRITER *w, struct addrinfo * address)
00320 {
00321 if (w == 0) {
00322 return 0;
00323 }
00324 RDD_TCP_WRITER *state = w->state;
00325
00326 if (state->address == 0) {
00327 return (address == 0);
00328 }
00329
00330 if (address == 0) {
00331 return 0;
00332 }
00333 return compare_sockaddr(state->address->ai_addr, address->ai_addr);
00334 }
00335
00336 static int
00337 tcp_compare_address(RDD_WRITER *w, struct addrinfo * address, int *result)
00338 {
00339 if (w == 0) {
00340 return RDD_BADARG;
00341 }
00342 if (result == 0) {
00343 return RDD_BADARG;
00344 }
00345 *result = compare_writer_address(w, address);
00346 return RDD_OK;
00347 }
00348