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 u_int32_t print_pkt (struct nfq_data *tb) { int id = 0; struct nfqnl_msg_packet_hdr *ph; struct nfqnl_msg_packet_hw *hwph; u_int32_t mark,ifi; int ret; char *data; ph = nfq_get_msg_packet_hdr(tb); if (ph) { id = ntohl(ph->packet_id); printf("hw_protocol=0x%04x hook=%u id=%u ", ntohs(ph->hw_protocol), ph->hook, id); } hwph = nfq_get_packet_hw(tb); if (hwph) { int i, hlen = ntohs(hwph->hw_addrlen); printf("hw_src_addr="); for (i = 0; i < hlen-1; i++) printf("%02x:", hwph->hw_addr[i]); printf("%02x ", hwph->hw_addr[hlen-1]); } mark = nfq_get_nfmark(tb); if (mark) printf("mark=%u ", mark); ifi = nfq_get_indev(tb); if (ifi) printf("indev=%u ", ifi); ifi = nfq_get_outdev(tb); if (ifi) printf("outdev=%u ", ifi); ifi = nfq_get_physindev(tb); if (ifi) printf("physindev=%u ", ifi); ifi = nfq_get_physoutdev(tb); if (ifi) printf("physoutdev=%u ", ifi); ret = nfq_get_payload(tb, &data); if (ret >= 0) { printf("payload_len=%d ", ret); //processPacketData (data, ret); } fputc('\n', stdout); return id; }
static int verify_pkt (struct nfq_data *tb) { struct nfqnl_msg_packet_hdr *ph; struct nfqnl_msg_packet_hw *hwph; struct iphdr *iph; struct tcphdr *tcph; ph = nfq_get_msg_packet_hdr(tb); if(!ph) return -1; // check for IP if(ntohs(ph->hw_protocol) != 0x800) return -1; hwph = nfq_get_packet_hw(tb); if(!hwph) return -1; // only accept 6 byte hw addresses // this may fail with USB net. But we don't want to restricht that // anyway if(ntohs(hwph->hw_addrlen) != 6) return -1; // the rest are payload checks // error or less than ip+tcp headers if(nfq_get_payload(tb, (unsigned char **)&iph) < 40) return -1; // check for valid ipv4 header if((iph->version != 4) || (iph->ihl != 5)) return -1; // don't allow fragmentation if((ntohs(iph->frag_off) & 0x1fff) != 0) return -1; // only deal with tcp if(iph->protocol != 6) return -1; // and take a peak into the tcp header tcph = (struct tcphdr*)(((char*)iph)+20); // ignore anything that doesn't have a syn flag if(!tcph->syn) return -1; return 0; }
int get_info(struct nfq_data *tb, device_t *dev, char *ip_addr, uint16_t *port) { struct nfqnl_msg_packet_hw *hwph; struct iphdr *iph; struct tcphdr *tcph; hwph = nfq_get_packet_hw(tb); if(!hwph) return -1; memcpy(dev->hw_addr, hwph->hw_addr, 6); if(nfq_get_payload(tb, (unsigned char **)&iph) < 40) return -1; memcpy(ip_addr, &iph->saddr, 4); tcph = (struct tcphdr*)(((char*)iph)+20); *port = ntohs(tcph->dest); return 0; }
/* * Queue an incoming packet to the NKN DPI module * Packets that have HTTP data are alone queueud */ static u_int32_t queue_pkt_for_url_filtering(struct nfq_q_handle *qh, struct nfq_data *nfq_data, int64_t tid) { int id = 0; struct nfqnl_msg_packet_hdr *ph; #if 0 struct nfqnl_msg_packet_hw *hwph; #endif int64_t ret; unsigned char *data; nfqueue_dpi_xfer_t *xfer_data; struct iphdr *iph; struct tcphdr *tcph; ph = nfq_get_msg_packet_hdr(nfq_data); if (ph) id = ntohl(ph->packet_id); #if 0 hwph = nfq_get_packet_hw(nfq_data); if (hwph) { int i, hlen = ntohs(hwph->hw_addrlen); printf("hw_src_addr="); for (i = 0; i < hlen-1; i++) printf("%02x:", hwph->hw_addr[i]); printf("%02x ", hwph->hw_addr[hlen-1]); } #endif ret = nfq_get_payload(nfq_data, &data); iph = (struct iphdr *)data; tcph = (struct tcphdr *)(data + (iph->ihl * 4)); if (ntohs(iph->tot_len) == ((iph->ihl * 4) + (tcph->doff * 4))) { nfq_set_verdict(qh, id, NF_ACCEPT, 0, NULL); AO_fetch_and_add1(&glob_dpi_filter_non_data_cnt); return 0; #ifdef NFLOOP_NO_PROCESS } else { nfq_set_verdict(qh, id, NF_ACCEPT, 0, NULL); AO_fetch_and_add1(&glob_dpi_filter_non_data_cnt); return 0; #endif } xfer_data = nkn_calloc_type(1, sizeof(nfqueue_dpi_xfer_t), mod_nf_dpi_xfer_t); if (!xfer_data) { NKN_ASSERT(0); nfq_set_verdict(qh, id, NF_ACCEPT, 0, NULL); glob_dpi_filter_err_cnt[tid]; return -1; } xfer_data->buffer = data; xfer_data->qh = qh; xfer_data->pkt_id = id; xfer_data->pkt_len = ret + sizeof(struct ethhdr); xfer_data->ip_src = ntohl(iph->saddr); xfer_data->ip_dst = ntohl(iph->daddr); #ifdef PROCESS_IN_NF_THREAD nkn_dpi_process_packet(xfer_data, tid); #else NKN_MUTEX_LOCK(&nkn_nf_dpi_xfer_lock[tid]); TAILQ_INSERT_TAIL(&nkn_nf_dpi_xfer_list[tid], xfer_data, xfer_entries); pthread_cond_signal(&nkn_nf_dpi_xfer_cond[tid]); NKN_MUTEX_UNLOCK(&nkn_nf_dpi_xfer_lock[tid]); #endif return 0; }
static int pkt_decision(struct nfq_data *payload) { char *data; char *match, *folder, *url; PURL current; int payload_offset, data_len; struct iphdr *iph; struct tcphdr *tcp; #if defined(AEI_VDSL_CUSTOMER_CENTURYLINK) char domain[1024+1]=""; #endif match = folder = url = NULL; data_len = nfq_get_payload(payload, &data); if( data_len == -1 ) { #ifdef UFD_DEBUG printf("data_len == -1!!!!!!!!!!!!!!!, EXIT\n"); #endif exit(1); } #ifdef UFD_DEBUG printf("data_len=%d ", data_len); #endif iph = (struct iphdr *)data; tcp = (struct tcphdr *)(data + (iph->ihl << 2)); payload_offset = ((iph->ihl)<<2) + (tcp->doff<<2); match = (char *)(data + payload_offset); if(strstr(match, "GET ") == NULL && strstr(match, "POST ") == NULL && strstr(match, "HEAD ") == NULL) { #ifdef UFD_DEBUG printf("****NO HTTP INFORMATION!!!\n"); #endif return PKT_ACCEPT; } #if defined(AEI_VDSL_CUSTOMER_CENTURYLINK) else{ AEI_getdomain(match, domain); } #endif #ifdef UFD_DEBUG printf("####payload = %s\n\n", match); #endif #if defined (AEI_WLAN_URL_REDIRECT) { char mac_str[128]={0}; char url_redirect[256]={0}; char *pUrl = NULL; struct nfqnl_msg_packet_hw *hw = NULL; hw = nfq_get_packet_hw(payload); if ( tcp->dest == htons (WEB_PORT) && (strstr(match,"GET / HTTP/")|| strstr(match,"get / HTTP/")|| strstr(match,"GET /"))|| strstr(match,"get /") ) { sprintf(mac_str,"%02x:%02x:%02x:%02x:%02x:%02x",hw->hw_addr[0],hw->hw_addr[1],hw->hw_addr[2], hw->hw_addr[3],hw->hw_addr[4],hw->hw_addr[5]); AEI_processSSID234UrlRedirect(mac_str,url_redirect,sizeof(url_redirect)-1,brname,match); if (strcmp(url_redirect,"")){ AEI_urltrim(url_redirect); pUrl = strstr(url_redirect,"http://"); if(pUrl){ pUrl = pUrl + 7; if (strstr(match, pUrl) == NULL) { // status = send_redirect (qh, id, payload, url_redirect); memset(GlbRedirectUrl, 0, sizeof(GlbRedirectUrl)); sprintf(GlbRedirectUrl, "%s", url_redirect); return PKT_REDIRECT; } }else{ if (strstr(match, url_redirect) == NULL) { // status = send_redirect (qh, id, payload, url_redirect); memset(GlbRedirectUrl, 0, sizeof(GlbRedirectUrl)); sprintf(GlbRedirectUrl, "%s", url_redirect); return PKT_REDIRECT; } } } } } #endif #if defined (DMP_CAPTIVEPORTAL_1) #if defined(AEI_VDSL_TR098_QWEST) if ((flagOneTimeRedirect == 1) && (tcp->dest == htons (WEB_PORT))) { if(strstr(match, "GET / HTTP/") || strstr(match, "get HTTP/")) { flagOneTimeRedirect = 2; AEI_send_msg_to_set_oneTimeRedirectURLFlag(); if ((strstr(match, oneTimeRedirectURL) == NULL) && (strstr(oneTimeRedirectIPAdress, inet_ntoa(*(struct in_addr *) &iph->daddr)) == NULL)) { //status = send_redirect (qh, id, payload, oneTimeRedirectURL); //return status; memset(GlbRedirectUrl, 0, sizeof(GlbRedirectUrl)); sprintf(GlbRedirectUrl, "%s", oneTimeRedirectURL); return PKT_REDIRECT; } } } else if ((flagOneTimeRedirect == 2) && (tcp->dest == htons (WEB_PORT))) { if ((strstr(match, "GET / HTTP/") || strstr(match, "get / HTTP/"))) { if ((strstr(match, oneTimeRedirectURL) == NULL) && (strstr(oneTimeRedirectIPAdress, inet_ntoa(*(struct in_addr *) &iph->daddr)) == NULL)) { flagOneTimeRedirect = 0; #if defined(AEI_VDSL_CUSTOMER_CENTURYLINK) if ((flagCaptiveURL == 1) && ((!AEI_checkCaptiveAllowList(captiveAllowList, iph->daddr)) &&(domain[0] && (!AEI_checkCaptiveAllowDomain(captiveAllowDomain, domain))))) #else if ((flagCaptiveURL == 1) && (!AEI_checkCaptiveAllowList(captiveAllowList, iph->daddr))) #endif { if ((strstr(match, captiveURL) == NULL) && (strstr(captiveIPAddr, inet_ntoa(*(struct in_addr *) &iph->daddr)) == NULL)) { //status = send_redirect (qh, id, payload, captiveURL); //return status; memset(GlbRedirectUrl, 0, sizeof(GlbRedirectUrl)); sprintf(GlbRedirectUrl, "%s", captiveURL); return PKT_REDIRECT; } } } } } else #endif { #if defined(AEI_VDSL_CUSTOMER_CENTURYLINK) if ((flagCaptiveURL == 1) && (tcp->dest == htons (WEB_PORT)) && ((!AEI_checkCaptiveAllowList(captiveAllowList, iph->daddr)) &&(domain[0] && (!AEI_checkCaptiveAllowDomain(captiveAllowDomain, domain))))) #else if ((flagCaptiveURL == 1) && (tcp->dest == htons (WEB_PORT)) && (!AEI_checkCaptiveAllowList(captiveAllowList, iph->daddr))) #endif { if(strstr(match, "GET /") || strstr(match, "get /")) { if ((strstr(match, captiveURL) == NULL) && (strstr(captiveIPAddr, inet_ntoa(*(struct in_addr *) &iph->daddr)) == NULL)) { //status = send_redirect (qh, id, payload, captiveURL); flagCaptiveURL = 1; //return status; memset(GlbRedirectUrl, 0, sizeof(GlbRedirectUrl)); sprintf(GlbRedirectUrl, "%s", captiveURL); return PKT_REDIRECT; } } } #if defined(AEI_VDSL_CUSTOMER_CENTURYLINK) else if ((flagCaptiveURL == 2) && (tcp->dest == htons (WEB_PORT)) && ((!AEI_checkCaptiveAllowList(captiveAllowList, iph->daddr)) &&(domain[0] && (!AEI_checkCaptiveAllowDomain(captiveAllowDomain, domain))))) #else else if ((flagCaptiveURL == 2) && (tcp->dest == htons (WEB_PORT)) && (!AEI_checkCaptiveAllowList(captiveAllowList, iph->daddr))) #endif { if(strstr(match, "GET / HTTP/") || strstr(match, "get / HTTP/")) { if ((strstr(match, captiveURL) == NULL) && (strstr(captiveIPAddr, inet_ntoa(*(struct in_addr *) &iph->daddr)) == NULL)) { //status = send_redirect (qh, id, payload, captiveURL); flagCaptiveURL = 1; //return status; memset(GlbRedirectUrl, 0, sizeof(GlbRedirectUrl)); sprintf(GlbRedirectUrl, "%s", captiveURL); return PKT_REDIRECT; } } } } #endif #if defined(AEI_VDSL_CUSTOMER_NCS) AEI_HandleWebActivityLog(match, iph); #endif for (current = purl; current != NULL; current = current->next) { if (current->folder[0] != '\0') { folder = strstr(match, current->folder); } if ( (url = strstr(match, current->website)) != NULL ) { if (strcmp(listtype, "Exclude") == 0) { if ( (folder != NULL) || (current->folder[0] == '\0') ) { #if defined(AEI_VDSL_CUSTOMER_NCS) if (strstr(current->lanIP, "all") != NULL) { //block all PCs printf("All####This page is blocked by Exclude list!, into send_redirect\n"); #if defined(AEI_VDSL_CAPTIVE_PAGES) return PKT_REDIRECT; #else return PKT_DROP; #endif } else { //block specific PCs struct in_addr lanIP; inet_aton(current->lanIP, &lanIP); if (lanIP.s_addr == iph->saddr) { printf("IP####This page is blocked by Exclude list!, into send_redirect\n"); #if defined(AEI_VDSL_CAPTIVE_PAGES) return PKT_REDIRECT; #else return PKT_DROP; #endif } } #else #ifdef UFD_DEBUG printf("####This page is blocked by Exclude list!"); #endif return PKT_DROP; #endif } else { #ifdef UFD_DEBUG printf("###Website hits but folder no hit in Exclude list! packets pass\n"); #endif return PKT_ACCEPT; } } else { if ( (folder != NULL) || (current->folder[0] == '\0') ) { #ifdef UFD_DEBUG printf("####This page is accepted by Include list!"); #endif return PKT_ACCEPT; } else { #ifdef UFD_DEBUG printf("####Website hits but folder no hit in Include list!, packets drop\n"); #endif return PKT_DROP; } } } } if (url == NULL) { if (strcmp(listtype, "Exclude") == 0) { #ifdef UFD_DEBUG printf("~~~~No Url hits!! This page is accepted by Exclude list!\n"); #endif return PKT_ACCEPT; } else { #ifdef UFD_DEBUG printf("~~~~No Url hits!! This page is blocked by Include list!\n"); #endif return PKT_DROP; } } #ifdef UFD_DEBUG printf("~~~None of rules can be applied!! Traffic is allowed!!\n"); #endif return PKT_ACCEPT; }