int cb (struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *data) { int id; int len; int hlen; char *pkt; struct nfqnl_msg_packet_hdr *ph; struct nfqnl_msg_packet_hw *hwph; struct timeval tv; tv.tv_sec = 0; // init if ((ph = nfq_get_msg_packet_hdr(nfa))) id = ntohl(ph->packet_id); else id = 0; if ((hwph = nfq_get_packet_hw(nfa))) hlen = ntohs(hwph->hw_addrlen); else hlen = 0; /* hole payload ... falls es nicht klappt ... Paket durchreichen */ if ((len = nfq_get_payload (nfa, (char **) &pkt)) < 0) return nfq_set_verdict(qh, id, NF_ACCEPT, 0, NULL); nfq_get_timestamp(nfa,&tv); return nfq_set_verdict(qh, id, myworker (data, pkt, len,&tv) ? NF_DROP : NF_ACCEPT, 0, NULL); }
static inline int SetPktHdr ( NfqImpl* impl, struct nfq_data* nfad, DAQ_PktHdr_t* hdr, uint8_t** pkt ) { int len = nfq_get_payload(nfad, (char**)pkt); if ( len <= 0 ) return -1; hdr->caplen = ((uint32_t)len <= impl->snaplen) ? (uint32_t)len : impl->snaplen; hdr->pktlen = len; hdr->flags = 0; hdr->address_space_id = 0; // if nfq fails to provide a timestamp, we fall back on tod if ( nfq_get_timestamp(nfad, &hdr->ts) ) gettimeofday(&hdr->ts, NULL); hdr->ingress_index = nfq_get_physindev(nfad); hdr->egress_index = -1; hdr->ingress_group = -1; hdr->egress_group = -1; return 0; }
static inline int SetPktHdr ( NfqImpl* impl, struct nfq_data* nfad, DAQ_PktHdr_t* hdr, uint8_t** pkt ) { int len = nfq_get_payload(nfad, (char**)pkt); if ( len <= 0 ) return -1; hdr->caplen = ((uint32_t)len <= impl->snaplen) ? (uint32_t)len : impl->snaplen; hdr->pktlen = len; hdr->flags = 0; nfq_get_timestamp(nfad, &hdr->ts); hdr->device_index = nfq_get_physindev(nfad); return 0; }
static int cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *data) { int id = 0; struct nfqnl_msg_packet_hdr *ph; struct timeval tv, now; long long time_passed; long long wait_time; ph = nfq_get_msg_packet_hdr(nfa); if (ph) id = ntohl(ph->packet_id); /* figure out how long to delay this single packet */ nfq_get_timestamp(nfa, &tv); gettimeofday(&now, NULL); time_passed = diff_time(&tv, &now); /* see how much more we want to wait */ wait_time = sleep_for_mode - time_passed; if (wait_time < 0) goto accept; /* for multi second intervals we need to do this */ while (wait_time > 0) { long long sleep = wait_time; if (sleep > WAIT_MAX) sleep = WAIT_MAX; usleep(sleep); wait_time -= WAIT_MAX; } accept: return nfq_set_verdict(qh, id, NF_ACCEPT, 0, NULL); }
int NFQSetupPkt (Packet *p, struct nfq_q_handle *qh, void *data) { struct nfq_data *tb = (struct nfq_data *)data; int ret; char *pktdata; struct nfqnl_msg_packet_hdr *ph; ph = nfq_get_msg_packet_hdr(tb); if (ph != NULL) { p->nfq_v.id = ntohl(ph->packet_id); //p->nfq_v.hw_protocol = ntohs(p->nfq_v.ph->hw_protocol); p->nfq_v.hw_protocol = ph->hw_protocol; } p->nfq_v.mark = nfq_get_nfmark(tb); if (nfq_config.mode == NFQ_REPEAT_MODE) { if ((nfq_config.mark & nfq_config.mask) == (p->nfq_v.mark & nfq_config.mask)) { int iter = 0; if (already_seen_warning < MAX_ALREADY_TREATED) SCLogInfo("Packet seems already treated by suricata"); already_seen_warning++; do { ret = nfq_set_verdict(qh, p->nfq_v.id, NF_ACCEPT, 0, NULL); } while ((ret < 0) && (iter++ < NFQ_VERDICT_RETRY_TIME)); if (ret < 0) { SCLogWarning(SC_ERR_NFQ_SET_VERDICT, "nfq_set_verdict of %p failed %" PRId32 "", p, ret); } return -1 ; } } p->nfq_v.ifi = nfq_get_indev(tb); p->nfq_v.ifo = nfq_get_outdev(tb); #ifdef NFQ_GET_PAYLOAD_SIGNED ret = nfq_get_payload(tb, &pktdata); #else ret = nfq_get_payload(tb, (unsigned char **) &pktdata); #endif /* NFQ_GET_PAYLOAD_SIGNED */ if (ret > 0) { /* nfq_get_payload returns a pointer to a part of memory * that is not preserved over the lifetime of our packet. * So we need to copy it. */ if (ret > 65536) { /* Will not be able to copy data ! Set length to 0 * to trigger an error in packet decoding. * This is unlikely to happen */ SCLogWarning(SC_ERR_INVALID_ARGUMENTS, "NFQ sent too big packet"); SET_PKT_LEN(p, 0); } else { PacketCopyData(p, (uint8_t *)pktdata, ret); } } else if (ret == -1) { /* unable to get pointer to data, ensure packet length is zero. * This will trigger an error in packet decoding */ SET_PKT_LEN(p, 0); } ret = nfq_get_timestamp(tb, &p->ts); if (ret != 0) { memset (&p->ts, 0, sizeof(struct timeval)); gettimeofday(&p->ts, NULL); } p->datalink = DLT_RAW; return 0; }
/** * \brief Callback called by NetFilter when a packet with target QUEUE is matched. * * For TCP packet with flags different than SYN, just send it to NuAuth and * accept it. * * For other packet: First of all, fill a structure ::packet_idl (identifier, * timestamp, ...). Try to add the new packet to ::packets_list (fails if the * list is full). Ask an authentication to NuAuth using auth_request_send(), * If the packet can't be sended, remove it from the list. * * \return If an error occurs, returns 0, else returns 1. */ static int treat_packet(struct nfq_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *data) { packet_idl *current; struct queued_pckt q_pckt; struct nfqnl_msg_packet_hdr *ph; struct timeval timestamp; int ret; #ifdef HAVE_NFQ_INDEV_NAME struct nlif_handle *nlif_handle = (struct nlif_handle *) data; #endif debug_log_printf(DEBUG_AREA_PACKET, DEBUG_LEVEL_VERBOSE_DEBUG, "(*) New packet"); q_pckt.payload_len = nfq_get_payload(nfa, &(q_pckt.payload)); if (q_pckt.payload_len == -1) { log_area_printf(DEBUG_AREA_PACKET, DEBUG_LEVEL_INFO, "Unable to get payload"); return 0; } q_pckt.mark = nfq_get_nfmark(nfa); #ifdef HAVE_NFQ_INDEV_NAME if (!get_interface_information(nlif_handle, &q_pckt, nfa)) { log_area_printf(DEBUG_AREA_PACKET, DEBUG_LEVEL_INFO, "Can not get interfaces information for message"); return 0; } #else snprintf(q_pckt.indev, sizeof(q_pckt.indev), "*"); snprintf(q_pckt.physindev, sizeof(q_pckt.physindev), "*"); snprintf(q_pckt.outdev, sizeof(q_pckt.outdev), "*"); snprintf(q_pckt.physoutdev, sizeof(q_pckt.physoutdev), "*"); #endif ret = nfq_get_timestamp(nfa, ×tamp); if (ret == 0) { q_pckt.timestamp = timestamp.tv_sec; } else { q_pckt.timestamp = time(NULL); } if (look_for_tcp_flags ((unsigned char *) q_pckt.payload, q_pckt.payload_len)) { ph = nfq_get_msg_packet_hdr(nfa); if (ph) { q_pckt.packet_id = ntohl(ph->packet_id); auth_request_send(AUTH_CONTROL, &q_pckt); IPQ_SET_VERDICT(q_pckt.packet_id, NF_ACCEPT); RETURN_NO_LOG 1; } else { log_area_printf(DEBUG_AREA_PACKET, DEBUG_LEVEL_VERBOSE_DEBUG, "Can not get the packet headers"); return 0; } } current = calloc(1, sizeof(packet_idl)); current->nfmark = q_pckt.mark; current->timestamp = q_pckt.timestamp ; current->id = 0; if (current == NULL) { log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_MESSAGE, "Can not allocate packet_id"); return 0; } #ifdef PERF_DISPLAY_ENABLE gettimeofday(&(current->arrival_time), NULL); #endif /* Get unique identifier of packet in queue */ ph = nfq_get_msg_packet_hdr(nfa); if (ph) { current->id = ntohl(ph->packet_id); } else { free(current); log_area_printf(DEBUG_AREA_PACKET, DEBUG_LEVEL_INFO, "Can not get id for message"); return 0; } /* Try to add the packet to the list */ ret = padd(current); q_pckt.packet_id = current->id; if (ret == 0) { /* send an auth request packet */ if (!auth_request_send(AUTH_REQUEST, &q_pckt)) { int sandf = 0; /* send failure dropping packet */ IPQ_SET_VERDICT(q_pckt.packet_id, NF_DROP); /* we fail to send the packet so we free packet related to current */ /* search and destroy packet by packet_id */ sandf = psearch_and_destroy(q_pckt.packet_id, &(q_pckt.mark)); if (!sandf) { log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_WARNING, "Packet could not be removed: %u", q_pckt.packet_id); } } } return 1; }
static int packet_input(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *data) { divert_cb cb = (divert_cb) data; char *d; int len; int rc; unsigned int id; struct nfqnl_msg_packet_hdr *ph = nfq_get_msg_packet_hdr(nfa); struct ip *ip; int flags = 0; struct timeval tv; int rlen = 0; void *rdata = NULL; len = nfq_get_payload(nfa, &d); if (len < 0) err(1, "nfq_get_payload()"); if (nfq_get_indev(nfa)) flags |= DF_IN; if (nfq_get_timestamp(nfa, &tv) == 0) set_time(&tv); else { static int warn = 0; if (!warn && !_conf.cf_disable_timers) xprintf(XP_ALWAYS, "No timestamp provided in packet" " - expect low performance due to" " calls to gettimeofday\n"); warn = 1; } rc = cb(d, len, flags); id = ntohl(ph->packet_id); switch (rc) { case DIVERT_MODIFY: ip = (struct ip*) d; rlen = ntohs(ip->ip_len); rdata = d; /* fallthrough */ case DIVERT_ACCEPT: if (_mark) { unsigned int mark = 0; assert((mark & _mark) == 0); nfq_set_verdict_mark(qh, id, NF_REPEAT, htonl(_mark | mark), rlen, rdata); } else nfq_set_verdict(qh, id, NF_ACCEPT, rlen, rdata); break; case DIVERT_DROP: nfq_set_verdict(qh, id, NF_DROP, 0, NULL); break; default: printf("Unknown verdict %d\n", rc); abort(); } return 0; }