//Parses a label into a C-string containing a dotted //Returns pointer to start of next fields in packet static char* labelToStr(char *packet, char *labelPtr, int packetSz, char *res, int resMaxLen) { int i, j, k; char *endPtr=NULL; i=0; do { if ((*labelPtr&0xC0)==0) { j=*labelPtr++; //skip past length //Add separator period if there already is data in res if (i<resMaxLen && i!=0) res[i++]='.'; //Copy label to res for (k=0; k<j; k++) { if ((labelPtr-packet)>packetSz) return NULL; if (i<resMaxLen) res[i++]=*labelPtr++; } } else if ((*labelPtr&0xC0)==0xC0) { //Compressed label pointer endPtr=labelPtr+2; int offset=local_ntohs(((uint16_t *)labelPtr))&0x3FFF; //Check if offset points to somewhere outside of the packet if (offset>packetSz) return NULL; labelPtr=&packet[offset]; } //check for out-of-bound-ness if ((labelPtr-packet)>packetSz) return NULL; } while (*labelPtr!=0); res[i]=0; //zero-terminate if (endPtr==NULL) endPtr=labelPtr+1; return endPtr; }
//Receive a DNS packet and maybe send a response back static void captdnsRecv(struct sockaddr_in *premote_addr, char *pusrdata, unsigned short length) { int i; char *buff = (char*)zalloc(DNS_LEN); char *reply = (char*)zalloc(DNS_LEN); char *rend=reply+length; char *p=pusrdata; DnsHeader *hdr=(DnsHeader*)p; DnsHeader *rhdr=(DnsHeader*)reply; p+=sizeof(DnsHeader); // printf("DNS packet: id 0x%X flags 0x%X rcode 0x%X qcnt %d ancnt %d nscount %d arcount %d len %d\n", // local_ntohs(&hdr->id), hdr->flags, hdr->rcode, local_ntohs(&hdr->qdcount), local_ntohs(&hdr->ancount), local_ntohs(&hdr->nscount), local_ntohs(&hdr->arcount), length); //Some sanity checks: if (length>512) goto finish; //Packet is longer than DNS implementation allows,512 if (length<sizeof(DnsHeader)) goto finish; //Packet is too short if (hdr->ancount || hdr->nscount || hdr->arcount) goto finish; //this is a reply, don't know what to do with it if (hdr->flags&FLAG_TC) goto finish; //truncated, can't use this //Reply is basically the request plus the needed data memcpy(reply, pusrdata, length); rhdr->flags|=FLAG_QR; for (i=0; i<local_ntohs(&hdr->qdcount); i++) { //Grab the labels in the q string p=labelToStr(pusrdata, p, length, buff, DNS_LEN); if (p==NULL) goto finish; DnsQuestionFooter *qf=(DnsQuestionFooter*)p; p+=sizeof(DnsQuestionFooter); printf("DNS: Q (type 0x%X class 0x%X) for %s\n", local_ntohs(&qf->type), local_ntohs(&qf->class), buff); if (local_ntohs(&qf->type)==QTYPE_A) { //They want to know the IPv4 address of something. //Build the response. rend=strToLabel(buff, rend, DNS_LEN-(rend-reply)); //Add the label if (rend==NULL) goto finish; DnsResourceFooter *rf=(DnsResourceFooter *)rend; rend+=sizeof(DnsResourceFooter); setn16(&rf->type, QTYPE_A); setn16(&rf->class, QCLASS_IN); setn32(&rf->ttl, 0); setn16(&rf->rdlength, 4); //IPv4 addr is 4 bytes; //Grab the current IP of the softap interface struct ip_info info; wifi_get_ip_info(SOFTAP_IF, &info); *rend++=ip4_addr1(&info.ip); *rend++=ip4_addr2(&info.ip); *rend++=ip4_addr3(&info.ip); *rend++=ip4_addr4(&info.ip); setn16(&rhdr->ancount, local_ntohs(&rhdr->ancount)+1); // printf("Added A rec to resp. Resp len is %d\n", (rend-reply)); } else if (local_ntohs(&qf->type)==QTYPE_NS) {
static PyObject * parse_tuple_message(PyObject *self, PyObject *args) { PyObject *prerob, *rob, *temp_tup; PyObject *typ; const char *data; Py_ssize_t dlen = 0; uint16_t natts = 0; if (!PyArg_ParseTuple(args, "Oy#", &typ, &data, &dlen)) return(NULL); if (dlen < 2) { PyErr_Format(PyExc_ValueError, "invalid tuple message: %d bytes is too small", dlen); return(NULL); } memcpy(&natts, data, 2); natts = local_ntohs(natts); prerob = PyTuple_New(natts); if (prerob == NULL) return(NULL); if (_unpack_tuple_data(prerob, natts, data+2, dlen-2) < 0) { Py_DECREF(prerob); return(NULL); } temp_tup = PyTuple_New(1); if (temp_tup == NULL) { Py_DECREF(prerob); return(NULL); } PyTuple_SET_ITEM(temp_tup, 0, prerob); rob = PyObject_CallObject(typ, temp_tup); Py_DECREF(temp_tup); return(rob); }