int init_netlink() { h = ipq_create_handle(0, PF_INET); if(h == NULL){ printf("%s\n", ipq_errstr()); return 0; } unsigned char mode = IPQ_COPY_PACKET; int range = sizeof(buf); int ret = ipq_set_mode(h, mode, range); }
void ipq_perror(const char *s) { if (s) fputs(s, stderr); else fputs("ERROR", stderr); if (ipq_errno) fprintf(stderr, ": %s", ipq_errstr()); if (errno) fprintf(stderr, ": %s", strerror(errno)); fputc('\n', stderr); }
static int init_netlink() { //printf("in netlink\n"); h = ipq_create_handle(0, PF_INET); if(h == NULL){ printf("%s\n", ipq_errstr()); return 0; } //printf("ipq_creat_handle success!\n"); unsigned char mode = IPQ_COPY_PACKET; int range = sizeof(buf); int ret = ipq_set_mode(h, mode, range); //printf("ipq_set_mode: send bytes =%d, range=%d\n", ret,range); signal(SIGINT, sigproc); //printf("out netlink\n"); }
int main(void) { int status; unsigned char buf[BUFSIZE]; packet_list_t *element; ipq_packet_msg_t *pmsg; delay_init(); pthread_t thread; pthread_create(&thread, NULL, _pkg_reinject, NULL); do { /* read packets from buffer */ status = ipq_read(h, buf, BUFSIZE, 0); if (status > 0) { switch (ipq_message_type(buf)) { case NLMSG_ERROR: printf("Received error message %d\n", ipq_get_msgerr(buf)); break; case IPQM_PACKET: { /* adding packet to pool */ ipq_packet_msg_t *m = ipq_get_packet(buf); pmsg = (ipq_packet_msg_t*)malloc(sizeof(ipq_packet_msg_t) + m->data_len); memcpy(pmsg, m, sizeof(ipq_packet_msg_t) + m->data_len); element = (packet_list_t *)malloc(sizeof(packet_list_t)); element->pmsg = pmsg; list_add_tail(&(element->list), &pkg_list); count_packet++; break; } default: printf("Unknown message type!\n"); break; } } else printf("ipq_read error return: %s\n",ipq_errstr()); } while (1); return 0; }
static int ipq_daq_acquire ( void* handle, int cnt, DAQ_Analysis_Func_t callback, void* user) { IpqImpl* impl = (IpqImpl*)handle; int n = 0; DAQ_PktHdr_t hdr; // If cnt is <= 0, don't limit the packets acquired. However, // impl->count = 0 has a special meaning, so interpret accordingly. impl->count = (cnt == 0) ? -1 : cnt; hdr.device_index = 0; hdr.flags = 0; while ( impl->count < 0 || n < impl->count ) { int ipqt, status = ipq_read( impl->ipqh, impl->buf, MSG_BUF_SIZE, impl->timeout); if ( status <= 0 ) { if ( status < 0 ) { DPE(impl->error, "%s: ipq_read=%d error %s", __FUNCTION__, status, ipq_errstr()); return DAQ_ERROR; } return 0; } ipqt = ipq_message_type(impl->buf); if ( ipqt == IPQM_PACKET ) { DAQ_Verdict verdict; ipq_packet_msg_t* ipqm = ipq_get_packet(impl->buf); SetPktHdr(impl, ipqm, &hdr); impl->stats.hw_packets_received++; if ( impl->fcode.bf_insns && sfbpf_filter(impl->fcode.bf_insns, ipqm->payload, hdr.caplen, hdr.caplen) == 0 ) { verdict = DAQ_VERDICT_PASS; impl->stats.packets_filtered++; } else { verdict = callback(user, &hdr, (uint8_t*)ipqm->payload); impl->stats.verdicts[verdict]++; impl->stats.packets_received++; } if ( impl->passive ) verdict = DAQ_VERDICT_PASS; switch ( verdict ) { case DAQ_VERDICT_BLOCK: case DAQ_VERDICT_BLACKLIST: status = ipq_set_verdict( impl->ipqh, ipqm->packet_id, NF_DROP, 0, NULL); break; case DAQ_VERDICT_REPLACE: status = ipq_set_verdict( impl->ipqh, ipqm->packet_id, NF_ACCEPT, hdr.pktlen, ipqm->payload); break; case DAQ_VERDICT_PASS: case DAQ_VERDICT_WHITELIST: case DAQ_VERDICT_IGNORE: default: status = ipq_set_verdict( impl->ipqh, ipqm->packet_id, NF_ACCEPT, 0, NULL); break; } if ( status < 0 ) { DPE(impl->error, "%s: ipq_set_verdict=%d error %s", __FUNCTION__, status, ipq_errstr()); return DAQ_ERROR; } n++; } else { // NLMSG_ERROR is supposed to be the only other valid type status = ipq_get_msgerr(impl->buf); DPE(impl->error, "%s: ipq_message_type=%d error=%d %s", __FUNCTION__, ipqt, status, ipq_errstr()); // ipq_message_type=2 error=1 Timeout // keep looping upon timeout or other errors } } return 0; }
static int ipq_daq_initialize ( const DAQ_Config_t* cfg, void** handle, char* errBuf, size_t errMax) { int status; if(cfg->name && *(cfg->name)) { snprintf(errBuf, errMax, "The ipq DAQ module does not support interface or readback mode!"); return DAQ_ERROR_INVAL; } IpqImpl* impl = calloc(1, sizeof(*impl)); if ( !impl ) { snprintf(errBuf, errMax, "%s: failed to allocate the ipq context!", __FUNCTION__); return DAQ_ERROR_NOMEM; } if ( ipq_daq_get_setup(impl, cfg, errBuf, errMax) != DAQ_SUCCESS ) { ipq_daq_shutdown(impl); return DAQ_ERROR; } impl->buf = malloc(MSG_BUF_SIZE); if ( !impl->buf ) { snprintf(errBuf, errMax, "%s: failed to allocate the ipq buffer!", __FUNCTION__); ipq_daq_shutdown(impl); return DAQ_ERROR_NOMEM; } // remember to also link in, eg: // iptables -A OUTPUT -p icmp -j QUEUE impl->ipqh = ipq_create_handle(0, impl->proto); if ( !impl->ipqh ) { snprintf(errBuf, errMax, "%s: ipq_create_handle error %s\n", __FUNCTION__, ipq_errstr()); ipq_daq_shutdown(impl); return DAQ_ERROR; } // copy both packet metadata and packet payload // paket payload is limited to IP_MAXPACKET status = ipq_set_mode(impl->ipqh, IPQ_COPY_PACKET, IP_MAXPACKET); if ( status < 0 ) { snprintf(errBuf, errMax, "%s: ipq_set_mode error %s\n", __FUNCTION__, ipq_errstr()); ipq_daq_shutdown(impl); return DAQ_ERROR; } if ( impl->device && strcasecmp(impl->device, "ip") ) { impl->link = eth_open(impl->device); if ( !impl->link ) { snprintf(errBuf, errMax, "%s: can't open %s!\n", __FUNCTION__, impl->device); ipq_daq_shutdown(impl); return DAQ_ERROR; } } else { impl->net = ip_open(); if ( !impl->net ) { snprintf(errBuf, errMax, "%s: can't open ip!\n", __FUNCTION__); ipq_daq_shutdown(impl); return DAQ_ERROR; } } impl->state = DAQ_STATE_INITIALIZED; *handle = impl; return DAQ_SUCCESS; }
static void packet_input(int fd) #endif { rt_table_t *fwd_rt, *rev_rt, *next_hop_rt = NULL; struct in_addr dest_addr, src_addr; u_int8_t rreq_flags = 0; unsigned int ifindex; struct ip_data *ipd = NULL; int pkt_flags = 0; #ifdef NS_PORT ifindex = NS_IFINDEX; /* Always use ns interface */ fwd_rt = NULL; /* For broadcast we provide no next hop */ ipd = NULL; /* No ICMP messaging */ struct hdr_cmn *ch = HDR_CMN(p); struct hdr_ip *ih = HDR_IP(p); src_addr.s_addr = ih->saddr(); dest_addr.s_addr = ih->daddr(); /* If this is a TCP packet and we don't have a route, we should set the gratuituos flag in the RREQ. */ if (ch->ptype() == PT_TCP) { rreq_flags |= RREQ_GRATUITOUS; } #else int status; char buf[sizeof(struct nlmsghdr)+sizeof(ipq_packet_msg_t)+BUFSIZE]; char *dev_name; ipq_packet_msg_t *pkt; struct iphdr *ip; struct udphdr *udp; struct icmphdr *icmp = NULL; status = ipq_read(h, buf, sizeof(buf), -1); if (status < 0) { DEBUG(LOG_DEBUG, 0, "%s", ipq_errstr()); ipq_perror(NULL); return; } if (ipq_message_type(buf) == NLMSG_ERROR) { fprintf(stderr, "ERROR packet_input: Check that the ip_queue.o module is loaded.\n"); die(h); } pkt = ipq_get_packet(buf); #ifdef DEBUG_PACKET DEBUG(LOG_DEBUG, 0, "Protocol %u indev=%s outdev=%s\n", pkt->hw_protocol, pkt->indev_name, pkt->outdev_name); #endif if (pkt->hook == 0) dev_name = pkt->indev_name; else if (pkt->hook == 3) dev_name = pkt->outdev_name; else dev_name = NULL; /* We know from kaodv.c that this is an IP packet */ ip = (struct iphdr *) pkt->payload; dest_addr.s_addr = ip->daddr; src_addr.s_addr = ip->saddr; switch (ip->protocol) { /* Don't process AODV control packets (UDP on port 654). They are accounted for on the aodv socket */ case IPPROTO_UDP: udp = (struct udphdr *) ((char *) ip + (ip->ihl << 2)); if (ntohs(udp->dest) == AODV_PORT || ntohs(udp->source) == AODV_PORT) goto accept; break; /* If this is a TCP packet and we don't have a route, we should set the gratuituos flag in the RREQ. */ case IPPROTO_TCP: rreq_flags |= RREQ_GRATUITOUS; break; /* We set the gratuitous flag also on ICMP ECHO requests, since the destination will also need a route back for the reply... */ case IPPROTO_ICMP: icmp = (struct icmphdr *) ((char *) ip + (ip->ihl << 2)); if (icmp->type == ICMP_ECHO) rreq_flags |= RREQ_GRATUITOUS; #ifdef DEBUG_PACKET DEBUG(LOG_INFO, 0, "setting G flag for RREQ to %s", ip_to_str(dest_addr)); #endif break; #ifdef CONFIG_GATEWAY case IPPROTO_MIPE: if (internet_gw_mode) { ip = ip_pkt_decapsulate(ip); if (ip == NULL) { DEBUG(LOG_ERR, 0, "Decapsulation failed..."); exit(-1); } pkt_flags |= PKT_DEC; } break; #endif /* CONFIG_GATEWAY */ } #ifdef DEBUG_PACKET DEBUG(LOG_INFO, 0, "pkt to %s", ip_to_str(dest_addr)); #endif if (dev_name) { ifindex = name2index(dev_name); if (ifindex < 0) { DEBUG(LOG_ERR, 0, "name2index error!"); return; } } else ifindex = 0; #endif /* NS_PORT */ /* If the packet is not interesting we just let it go through... */ if (dest_addr.s_addr == AODV_BROADCAST || dest_addr.s_addr == DEV_IFINDEX(ifindex).broadcast.s_addr) { #ifdef NS_PORT /* Limit Non AODV broadcast packets (Rolf Winter * <[email protected]). */ ih->ttl() = ih->ttl() - 1; if(ih->ttl() < 1) Packet::free(p); else sendPacket(p, dest_addr, 0.0); return; #else goto accept; #endif } /* Find the entry of the neighboring node and the destination (if any). */ rev_rt = rt_table_find(src_addr); fwd_rt = rt_table_find(dest_addr); #ifdef CONFIG_GATEWAY /* Check if we have a route and it is an Internet destination (Should be * encapsulated and routed through the gateway). */ if (fwd_rt && (fwd_rt->state == VALID) && (fwd_rt->flags & RT_INET_DEST)) { /* The destination should be relayed through the IG */ rt_table_update_timeout(fwd_rt, ACTIVE_ROUTE_TIMEOUT); #ifdef NS_PORT p = pkt_encapsulate(p, fwd_rt->next_hop); if (p == NULL) { DEBUG(LOG_ERR, 0, "IP Encapsulation failed!"); return; } /* Update pointers to headers */ ch = HDR_CMN(p); ih = HDR_IP(p); #else ip = ip_pkt_encapsulate(ip, fwd_rt->next_hop, BUFSIZE); if (ip == NULL) { DEBUG(LOG_ERR, 0, "Minimal IP Encapsulation failed!"); exit(-1); } #endif dest_addr = fwd_rt->next_hop; fwd_rt = rt_table_find(dest_addr); pkt_flags |= PKT_ENC; } #endif /* CONFIG_GATEWAY */ /* UPDATE TIMERS on active forward and reverse routes... */ /* When forwarding a packet, we update the lifetime of the destination's routing table entry, as well as the entry for the next hop neighbor (if not the same). AODV draft 10, section 6.2. */ if (fwd_rt && fwd_rt->state == VALID && dest_addr.s_addr != DEV_IFINDEX(ifindex).ipaddr.s_addr) { rt_table_update_timeout(fwd_rt, ACTIVE_ROUTE_TIMEOUT); next_hop_rt = rt_table_find(fwd_rt->next_hop); if (next_hop_rt && next_hop_rt->state == VALID && next_hop_rt->dest_addr.s_addr != fwd_rt->dest_addr.s_addr) rt_table_update_timeout(next_hop_rt, ACTIVE_ROUTE_TIMEOUT); } /* Also update the reverse route and reverse next hop along the path back, since routes between originators and the destination are expected to be symmetric. */ if (rev_rt && rev_rt->state == VALID) { rt_table_update_timeout(rev_rt, ACTIVE_ROUTE_TIMEOUT); next_hop_rt = rt_table_find(rev_rt->next_hop); if (next_hop_rt && next_hop_rt->state == VALID && rev_rt && next_hop_rt->dest_addr.s_addr != rev_rt->dest_addr.s_addr) rt_table_update_timeout(next_hop_rt, ACTIVE_ROUTE_TIMEOUT); /* Update HELLO timer of next hop neighbor if active */ if (!llfeedback && next_hop_rt->hello_timer.used) { struct timeval now; gettimeofday(&now, NULL); hello_update_timeout(next_hop_rt, &now, ALLOWED_HELLO_LOSS * HELLO_INTERVAL); } } /* OK, the timeouts have been updated. Now see if either: 1. The packet is for this node -> ACCEPT. 2. The packet is not for this node -> Send RERR (someone want's this node to forward packets although there is no route) or Send RREQ. */ /* If the packet is destined for this node, then just accept it. */ if (memcmp(&dest_addr, &DEV_IFINDEX(ifindex).ipaddr, sizeof(struct in_addr)) == 0) { #ifdef NS_PORT ch->size() -= IP_HDR_LEN; // cut off IP header size 4/7/99 -dam target_->recv(p, (Handler*)0); p = 0; return; #else goto accept; #endif } if (!fwd_rt || fwd_rt->state == INVALID || (fwd_rt->hcnt == 1 && (fwd_rt->flags & RT_UNIDIR))) { /* Check if the route is marked for repair or is INVALID. In * that case, do a route discovery. */ if (fwd_rt && (fwd_rt->flags & RT_REPAIR)) goto route_discovery; /* If a packet is received on the NF_IP_PRE_ROUTING hook, i.e. inbound on the interface and we don't have a route to the destination, we should send an RERR to the source and then drop the package... */ /* NF_IP_PRE_ROUTING = 0 */ #ifdef NS_PORT #define PACKET_IS_INBOUND ch->direction() == hdr_cmn::UP #else #define PACKET_IS_INBOUND pkt->hook == 0 #endif if (PACKET_IS_INBOUND) { struct in_addr rerr_dest; RERR *rerr; #ifdef NS_PORT struct in_addr nh; nh.s_addr = ch->prev_hop_; DEBUG(LOG_DEBUG, 0, "No route, src=%s dest=%s prev_hop=%s - DROPPING!", ip_to_str(src_addr), ip_to_str(dest_addr), ip_to_str(nh)); #endif if (fwd_rt) { rerr = rerr_create(0, fwd_rt->dest_addr, fwd_rt->dest_seqno); rt_table_update_timeout(fwd_rt, DELETE_PERIOD); } else rerr = rerr_create(0, dest_addr, 0); DEBUG(LOG_DEBUG, 0, "Sending RERR to prev hop %s for unknown dest %s", ip_to_str(src_addr), ip_to_str(dest_addr)); /* Unicast the RERR to the source of the data transmission * if possible, otherwise we broadcast it. */ if (rev_rt && rev_rt->state == VALID) rerr_dest = rev_rt->next_hop; else rerr_dest.s_addr = AODV_BROADCAST; aodv_socket_send((AODV_msg *) rerr, rerr_dest, RERR_CALC_SIZE(rerr), 1, &DEV_IFINDEX(ifindex)); if (wait_on_reboot) { DEBUG(LOG_DEBUG, 0, "Wait on reboot timer reset."); timer_set_timeout(&worb_timer, DELETE_PERIOD); } #ifdef NS_PORT /* DEBUG(LOG_DEBUG, 0, "Dropping pkt uid=%d", ch->uid()); */ drop(p, DROP_RTR_NO_ROUTE); #else status = ipq_set_verdict(h, pkt->packet_id, NF_DROP, 0, NULL); if (status < 0) die(h); #endif return; } route_discovery: /* Buffer packets... Packets are queued by the ip_queue.o module already. We only need to save the handle id, and return the proper verdict when we know what to do... */ #ifdef NS_PORT packet_queue_add(p, dest_addr); #else packet_queue_add(pkt->packet_id, dest_addr, ip); #ifdef CONFIG_GATEWAY /* In gateway mode we handle packets in userspace */ ipq_set_verdict(h, pkt->packet_id, NF_DROP, 0, NULL); #endif /* Already seeking the destination? Then do not allocate any memory or generate a RREQ. */ if (seek_list_find(dest_addr)) return; /* If the request is generated locally by an application, we save the IP header + 64 bits of data for sending an ICMP Destination Host Unreachable in case we don't find a route... */ if (src_addr.s_addr == DEV_IFINDEX(ifindex).ipaddr.s_addr && ip && pkt->data_len >= (ip->ihl << 2) + 8) { ipd = (struct ip_data *) malloc(sizeof(struct ip_data)); if (ipd == NULL) { perror("Malloc for IP data failed!"); exit(-1); } /* IP header + 64 bits data (8 bytes) */ ipd->len = (ip->ihl << 2) + 8; memcpy(ipd->data, ip, ipd->len); } else ipd = NULL; #endif if (fwd_rt && (fwd_rt->flags & RT_REPAIR)) rreq_local_repair(fwd_rt, src_addr, ipd); else rreq_route_discovery(dest_addr, rreq_flags, ipd); return; } else { #ifdef NS_PORT /* DEBUG(LOG_DEBUG, 0, "Sending pkt uid=%d", ch->uid()); */ sendPacket(p, fwd_rt->next_hop, 0.0); #else accept: if (pkt_flags & PKT_ENC || (pkt_flags & PKT_DEC)) status = ipq_set_verdict(h, pkt->packet_id, NF_ACCEPT, ntohs(ip->tot_len), (unsigned char *)ip); else status = ipq_set_verdict(h, pkt->packet_id, NF_ACCEPT, 0, NULL); if (status < 0) die(h); #endif /* When forwarding data, make sure we are sending HELLO messages */ gettimeofday(&this_host.fwd_time, NULL); if (!llfeedback && optimized_hellos) hello_start(); } }
// Main entry point to application int main(int argc, char *argv[]) { BYTE MsgBuff[MAXIPQMSG]; struct sigaction SigAction; int i; // Read config & parameters if(!ReadConfig(argc, argv)) return EXIT_FAILURE; // If we should act as neither a master nor a client (config error) if(!(Config.Flags & CONFIGFLAGS_MASTER) && !(Config.Flags & CONFIGFLAGS_CLIENT)){ printf(APPTITLE": not configured to run as a master nor client\n"); return EXIT_FAILURE; } // If we're to be a client, check we have an IP if(Config.Flags & CONFIGFLAGS_CLIENT && Config.MasterIp[0] == 0x00){ printf(APPTITLE": Can not run as a client, no master IP specified 0x%02X\n", Config.Flags); return EXIT_FAILURE; } // Let the user know we're thinking of them if(Config.Flags & CONFIGFLAGS_MASTER) Log(LOG_NOTICE, "Acting as a master on port %d", Config.MasterPort); if(Config.Flags & CONFIGFLAGS_SELFCLIENT) Log(LOG_NOTICE, "Acting as a self-client with %d packet queues", Config.Queue); if(Config.Flags & CONFIGFLAGS_CLIENT) Log(LOG_NOTICE, "Acting as a client to %s:%d with %d packet queues", Config.MasterIp, Config.MasterPort, Config.Queue); else Log(LOG_NOTICE, "Acting stupid"); // If we should daemonise if(Config.Flags & CONFIGFLAGS_DAEMON) // Daemonise Daemon(); // If we should act as a master if(Config.Flags & CONFIGFLAGS_MASTER){ // If we should act as _only_ a master if(!(Config.Flags & CONFIGFLAGS_CLIENT) && !(Config.Flags & CONFIGFLAGS_SELFCLIENT)){ // Jump to main function in master.c which will perform this function MasterRun(NULL); return EXIT_SUCCESS; } // If we should act as a client as well else{ // Start main thread in master.c which will perform this function pthread_create(&idMasterThread, NULL, &MasterRun, NULL); } } // Create an IPQ handle hIpq = ipq_create_handle(0, PF_INET); if(hIpq == NULL){ // If we're running a master thread if(idMasterThread){ // Set flag & wait for master thread to exit ExitMasterThread = 1; pthread_join(idMasterThread, NULL); } // Log it Log(LOG_ERR, "Failed to initialise IPQ (%s)", ipq_errstr()); return EXIT_FAILURE; } // Set mode. Note: We set to packet mode so that we get to see the // number of bytes in the payload, the payload itself is ignored if (ipq_set_mode(hIpq, IPQ_COPY_PACKET, 0) == -1){ // If we're running a master thread if(idMasterThread){ // Set flag & wait for master thread to exit ExitMasterThread = 1; pthread_join(idMasterThread, NULL); } // Release IPQ ipq_destroy_handle(hIpq); // Tell the user Log(LOG_ERR, "Failed to configure IPQ (%s)", ipq_errstr()); return EXIT_FAILURE; } // Allocate Packet queue memory for(i = 0; i < PacketQueues; i++) PacketQueue[i] = malloc(Config.Queue * sizeof(struct ipq_packet_msg)); // Check allocations worked if(!PacketQueue){ // Free anything that was allocated if(PacketQueue) free(PacketQueue); // If we're running a master thread if(idMasterThread){ // Set flag & wait for master thread to exit ExitMasterThread = 1; pthread_join(idMasterThread, NULL); } // Release IPQ ipq_destroy_handle(hIpq); // Tell the user Log(LOG_ERR, "Failed to allocate sufficant memory"); return EXIT_FAILURE; } // Inititalise the PacketQueue mutex pthread_mutex_init(&PacketQueueMutex, NULL); // If we're acting as a normal client if(Config.Flags & CONFIGFLAGS_CLIENT) // Start control thread pthread_create(&idControlThread, NULL, &ControlRun, NULL); // Install SIGTERM/etc handler to get out of 'while(!ExitMain)' memset(&SigAction, 0, sizeof(SigAction)); SigAction.sa_handler = SignalHandler; sigaction(SIGINT, &SigAction, NULL); sigaction(SIGQUIT, &SigAction, NULL); sigaction(SIGTERM, &SigAction, NULL); // Install SIGHUP handler to reread config sigaction(SIGHUP, &SigAction, NULL); // Tell user Log(LOG_INFO, "Client up and running"); // Enter main loop while(!ExitMain){ // Wait up to 100mS to recieve a message int MsgSize = ipq_read(hIpq, MsgBuff, MAXIPQMSG, 100); // Error getting message if(MsgSize == -1){ // TODO: This has started to happen occasionally. Don't know why. // ipq_errstr() = "Failed to receive netlink message" // Tell the user Log(LOG_ERR, "Error reading message from IPQ (%s)", ipq_errstr()); } // Timeout getting message else if(MsgSize == 0){ // Do background processing BackgroundProcessing(); } // Got a message else{ // Switch on message type switch (ipq_message_type(MsgBuff)){ case NLMSG_ERROR: // Apparently we should call this (to clear the error?) ipq_get_msgerr(MsgBuff); // Tell the user Log(LOG_ERR, "Error reading message type from IPQ (%s)", ipq_errstr()); break; case IPQM_PACKET: // Call a function to process the packet ProcessPacketMessage(ipq_get_packet(MsgBuff)); // Do background processing BackgroundProcessing(); break; default: // Tell the user Log(LOG_WARNING, "Undefined message type from IPQ"); break; } } } // If we're running a control thread if(idControlThread){ // Set flag & wait for control thread to exit ExitControlThread = 1; pthread_join(idControlThread, NULL); } // If we're running a master thread if(idMasterThread){ // Set flag & wait for master thread to exit ExitMasterThread = 1; pthread_join(idMasterThread, NULL); } // Release IPQ ipq_destroy_handle(hIpq); // Release Packet queue memory for(i = 0; i < PacketQueues; i++) free(PacketQueue[i]); // Let the user know we're thinking of them Log(LOG_INFO, "Exited cleanly"); return EXIT_SUCCESS; }
/* returns a bound socket matching a connection request * * sets verdict on request packet if ipq or nfq was used and the port is already bound * * in the latter case, -1 is returned */ int get_boundsock(struct sockaddr_in *server_addr, uint16_t port, int type) { int fd, sockopt; #ifdef USE_IPQ_MON int status; #endif if ((type != SOCK_DGRAM) && (type != SOCK_STREAM)) { logmsg(LOG_ERR, 1, "Error - Socket type %d not supported.\n", type); exit(EXIT_FAILURE); } if (!(fd = socket(AF_INET, type, 0))) { logmsg(LOG_ERR, 1, "Error - Could not create socket: %m.\n"); exit(EXIT_FAILURE); } sockopt = 1; if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(sockopt)) < 0) logmsg(LOG_WARN, 1, "Warning - Unable to set SO_REUSEADDR for server socket.\n"); bzero((char *) server_addr, sizeof(struct sockaddr_in)); server_addr->sin_family = AF_INET; server_addr->sin_addr.s_addr = bind_address.s_addr; server_addr->sin_port = port; if ((bind(fd, (struct sockaddr *) server_addr, sizeof(struct sockaddr_in))) != 0) { /* we already got one server process */ logmsg(LOG_DEBUG, 1, "Unable to bind to port %u/tcp: %m.\n", ntohs(port)); #ifdef USE_IPQ_MON /* hand packet processing back to the kernel */ if ((status = ipq_set_verdict(h, packet->packet_id, NF_ACCEPT, 0, NULL)) < 0) { logmsg(LOG_ERR, 1, "Error - Could not set verdict on packet: %s.\n", ipq_errstr()); ipq_destroy_handle(h); exit(EXIT_FAILURE); } logmsg(LOG_DEBUG, 1, "IPQ - Successfully set verdict on packet.\n"); return(-1); #else #ifdef USE_NFQ_MON /* hand packet processing back to the kernel */ /* nfq_set_verdict()'s return value is undocumented, * but digging the source of libnetfilter_queue and libnfnetlink reveals * that it's just the passed-through value of a sendmsg() */ if (nfq_set_verdict(qh, id, NF_ACCEPT, 0, NULL) == -1) { logmsg(LOG_ERR, 1, "Error - Could not set verdict on packet.\n"); nfq_destroy_queue(qh); exit(EXIT_FAILURE); } logmsg(LOG_DEBUG, 1, "NFQ - Successfully set verdict on packet.\n"); /* a dynamic server is already present */ close(fd); return(-1); #else /* if bind() did not fail for 'port already in use' but for some other reason, * we're in troubles and want a verbose error message */ if (errno != 98) logmsg(LOG_NOISY, 1, "Warning - Could not bind to port %u/tcp: %m.\n", ntohs(port)); exit(EXIT_FAILURE); #endif #endif } logmsg(LOG_DEBUG, 1, "Socket created, file descriptor is %d.\n", fd); return(fd); }