00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00031 #include "nufw.h"
00032
00033 #include <stdlib.h>
00034 #include <time.h>
00035 #include <linux/icmp.h>
00036 #include <netinet/icmp6.h>
00037 #include <netinet/ip.h>
00038 #include <netinet/ip6.h>
00039
00040 #include <nubase.h>
00041
00042
00043
00044
00045 #ifdef PERF_DISPLAY_ENABLE
00046
00051 int timeval_substract(struct timeval *result, struct timeval *x,
00052 struct timeval *y)
00053 {
00054
00055 if (x->tv_usec < y->tv_usec) {
00056 int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
00057 y->tv_usec -= 1000000 * nsec;
00058 y->tv_sec += nsec;
00059 }
00060 if (x->tv_usec - y->tv_usec > 1000000) {
00061 int nsec = (x->tv_usec - y->tv_usec) / 1000000;
00062 y->tv_usec += 1000000 * nsec;
00063 y->tv_sec -= nsec;
00064 }
00065
00066
00067
00068 result->tv_sec = x->tv_sec - y->tv_sec;
00069 result->tv_usec = x->tv_usec - y->tv_usec;
00070
00071
00072 return x->tv_sec < y->tv_sec;
00073 }
00074 #endif
00075
00079 void close_tls_session()
00080 {
00081 if (tls.session == NULL)
00082 return;
00083
00084 pthread_mutex_destroy(&tls.auth_server_mutex);
00085 nussl_session_destroy(tls.session);
00086 tls.session = NULL;
00087 }
00088
00095 void psuppress(packet_idl * previous, packet_idl * current)
00096 {
00097 if (previous != NULL)
00098 previous->next = current->next;
00099 else
00100 packets_list.start = current->next;
00101 if (current->next == NULL) {
00102 packets_list.end = previous;
00103 }
00104 free(current);
00105 packets_list.length--;
00106 }
00107
00114 unsigned long padd(packet_idl * current)
00115 {
00116 if (track_size <= packets_list.length) {
00117 log_area_printf(DEBUG_AREA_PACKET, DEBUG_LEVEL_WARNING,
00118 "Warning: queue is full, dropping element");
00119 IPQ_SET_VERDICT(current->id, NF_DROP);
00120 return 0;
00121 }
00122
00123 packets_list.length++;
00124 current->next = NULL;
00125
00126 if (current->timestamp == 0) {
00127 current->timestamp = time(NULL);
00128 }
00129
00130 if (packets_list.end != NULL)
00131 packets_list.end->next = current;
00132 packets_list.end = current;
00133 if (packets_list.start == NULL)
00134 packets_list.start = current;
00135 return current->id;
00136 }
00137
00138
00139
00140
00148 int psearch_and_destroy(uint32_t packet_id, uint32_t * nfmark)
00149 {
00150 packet_idl *current = packets_list.start, *previous = NULL;
00151 int timestamp = time(NULL);
00152
00155 while (current != NULL) {
00156 if (current->id == packet_id) {
00157 #if HAVE_LIBIPQ_MARK || USE_NFQUEUE
00158 *nfmark = current->nfmark;
00159 #endif
00160
00161 #ifdef PERF_DISPLAY_ENABLE
00162 {
00163 struct timeval elapsed_time, leave_time;
00164 double ms;
00165 gettimeofday(&leave_time, NULL);
00166 timeval_substract(&elapsed_time,
00167 &leave_time,
00168 &(current->
00169 arrival_time));
00170 ms = (double) elapsed_time.tv_sec * 1000 +
00171 (double) elapsed_time.tv_usec / 1000;
00172 log_area_printf(DEBUG_AREA_PACKET,
00173 DEBUG_LEVEL_INFO,
00174 "Treatment time for connection: %.1f ms",
00175 ms);
00176 }
00177 #endif
00178
00179
00180 psuppress(previous, current);
00181 return 1;
00182
00183
00184 } else if (timestamp - current->timestamp > packet_timeout) {
00185 IPQ_SET_VERDICT(current->id, NF_DROP);
00186 debug_log_printf(DEBUG_AREA_PACKET, DEBUG_LEVEL_INFO,
00187 "Dropped: %lu", current->id);
00188 psuppress(previous, current);
00189 current = packets_list.start;
00190 previous = NULL;
00191 } else {
00192 previous = current;
00193 current = current->next;
00194 }
00195 }
00196 return 0;
00197 }
00198
00202 void clear_packet_list()
00203 {
00204 packet_idl *current = packets_list.start, *next;
00205 while (current != NULL) {
00206 next = current->next;
00207 free(current);
00208 current = next;
00209 }
00210 packets_list.start = NULL;
00211 packets_list.end = NULL;
00212 packets_list.length = 0;
00213 }
00214
00218 void clean_old_packets()
00219 {
00220 packet_idl *current = packets_list.start, *previous = NULL;
00221 int timestamp = time(NULL);
00222
00223 while (current != NULL) {
00224
00225 if (timestamp - current->timestamp > packet_timeout) {
00226 IPQ_SET_VERDICT(current->id, NF_DROP);
00227 debug_log_printf(DEBUG_AREA_PACKET,
00228 DEBUG_LEVEL_DEBUG, "Dropped: %lu",
00229 current->id);
00230 psuppress(previous, current);
00231 current = packets_list.start;
00232 previous = NULL;
00233 } else {
00234 current = NULL;
00235 }
00236 }
00237 }
00238
00239
00240
00241
00242
00243
00244 __u16 icmp_cksum(__u16 * buf, int nbytes)
00245 {
00246 __u32 sum;
00247 __u16 oddbyte;
00248
00249 sum = 0;
00250 while (nbytes > 1) {
00251 sum += *buf++;
00252 nbytes -= 2;
00253 }
00254
00255 if (nbytes == 1) {
00256 oddbyte = 0;
00257 *((__u16 *) & oddbyte) = *(__u16 *) buf;
00258 sum += oddbyte;
00259 }
00260
00261 sum = (sum >> 16) + (sum & 0xffff);
00262 sum += (sum >> 16);
00263
00264 return (__u16) ~ sum;
00265 }
00266
00267 int send_icmp_ipv4_unreach(char *payload)
00268 {
00269 struct sockaddr_in to;
00270 char buffer[sizeof(struct icmphdr) + 20 + 8];
00271 struct iphdr *ip = (struct iphdr *) payload;
00272 struct icmphdr *icmp = (struct icmphdr *) buffer;
00273
00274
00275 icmp->type = 3;
00276 icmp->code = 0;
00277 icmp->checksum = 0x0000;
00278 icmp->un.frag.__unused = 0;
00279 icmp->un.frag.mtu = 0;
00280
00281
00282 memcpy(buffer + sizeof(struct icmphdr), payload, 20 + 8);
00283
00284
00285 memset(&to, 0, sizeof(to));
00286 to.sin_family = AF_INET;
00287 to.sin_addr.s_addr = ip->saddr;
00288
00289
00290 icmp->checksum = icmp_cksum((__u16 *) buffer, sizeof(buffer));
00291
00292
00293 return sendto(raw_sock4, buffer, sizeof(buffer), 0,
00294 (struct sockaddr *) &to, sizeof(to));
00295 }
00296
00297 int send_icmp_ipv6_unreach(char *payload)
00298 {
00299 struct sockaddr_in6 to;
00300 char buffer[sizeof(struct icmp6_hdr) + 40 + 8];
00301 struct ip6_hdr *ip = (struct ip6_hdr *) payload;
00302 struct icmp6_hdr *icmp = (struct icmp6_hdr *) buffer;
00303
00304
00305 memset(icmp, 0, sizeof(*icmp));
00306 icmp->icmp6_type = 1;
00307 icmp->icmp6_code = 0;
00308
00309
00310
00311 memcpy(buffer + sizeof(*icmp), payload, 40 + 8);
00312
00313
00314 memset(&to, 0, sizeof(to));
00315 to.sin6_family = AF_INET6;
00316 to.sin6_addr = ip->ip6_src;
00317
00318 #ifdef LINUX
00319
00320 #else
00321 # error "You may compute the checksum!"
00322 #endif
00323
00324 if (raw_sock6 > 0) {
00325
00326 return sendto(raw_sock6, buffer, sizeof(buffer), 0,
00327 (struct sockaddr *) &to, sizeof(to));
00328 } else {
00329 return 0;
00330 }
00331 }
00332
00333 int send_icmp_unreach(char *payload)
00334 {
00335 struct iphdr *ip4 = (struct iphdr *) payload;
00336 if (ip4->version == AF_INET) {
00337 return send_icmp_ipv4_unreach(payload);
00338 } else {
00339 return send_icmp_ipv6_unreach(payload);
00340 }
00341 }