Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 3 Jun 2007 09:52:03 GMT
From:      Alexey Tarasov <taleks@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 120824 for review
Message-ID:  <200706030952.l539q3eC056262@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=120824

Change 120824 by taleks@taleks_th on 2007/06/03 09:51:31

	pxe_dns: implemented simple DNS resolving using UDP sockets. pxe_core: added set nameserver function, updated receiving cycle. pxe_filter: small changes to remove debug information. pxe_sock: first dummy implementation for UDP. pxe_udp: checksum calculation and socket writing update.

Affected files ...

.. //depot/projects/soc2007/taleks-pxe_http/pxe_arp.c#6 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_core.c#12 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_core.h#10 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_dns.c#2 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_dns.h#2 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_filter.c#2 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_sock.c#5 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_sock.h#5 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_udp.c#2 edit

Differences ...

==== //depot/projects/soc2007/taleks-pxe_http/pxe_arp.c#6 (text+ko) ====

@@ -183,15 +183,17 @@
 	 * or for proxy server. Default arp_table size is 8. It seems more than enough.
 	 */	
 	 
-	if (NULL != pxe_arp_table_search(arp_reply->body.src_paddr)) {
+	const MAC_ADDR *kmac = pxe_arp_table_search(arp_reply->body.src_paddr);
+	if (NULL != kmac) {
 #ifdef PXE_DEBUG
 	        uint8_t *octet = (uint8_t *)&arp_reply->body.src_paddr;
 		uint8_t *mac = arp_reply->body.src_hwaddr;
 	        printf("MAC of %d.%d.%d.%d already known: %x:%x:%x:%x:%x:%x\n",
 		    octet[0], octet[1], octet[2], octet[3],
-		    mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]
+		    (*kmac)[0], (*kmac)[1], (*kmac)[2], (*kmac)[3], (*kmac)[4], (*kmac)[5]
 		);
 #endif
+		/* NOTE: theoretically it's possible mac != known mac. Ignore for now. */
 		return (0);
 	}
 	
@@ -282,9 +284,6 @@
 
 		if (timeToDie == 0) {	
 
-#ifdef PXE_DEBUG_HELL
-			printf(".");
-#endif 
 			--trysLeft;
 			if (trysLeft == 0) { 	/* have not recieved anything, return nothing */
 

==== //depot/projects/soc2007/taleks-pxe_http/pxe_core.c#12 (text+ko) ====

@@ -752,7 +752,7 @@
 	}
 	
 #ifdef PXE_DEBUG
-	printf("recv_packets(): size = %d, proto = %d, frame_length = %d bytes\n.", buffer_size, protocol, frame_size);
+	printf("recv_packets(): size = %d, proto = %d, frame_length = %d bytes.\n", buffer_size, protocol, frame_size);
 #endif		
 
 	/* we are interested in ARP & IP packets */
@@ -776,7 +776,6 @@
 		drop_flag = 1;		/* drop this packet */
 	}
 	
-
 	/* checking first fragment, this may help to avoid memory allocation
 	 * and memblock copy in main cycle below
 	 */
@@ -814,7 +813,7 @@
 		      (!core_protocol[iphdr->protocol](&dummy_pack,
 				(buffer_size == frame_size) ? PXE_CORE_HANDLE : PXE_CORE_FRAG, NULL)) ) {
 
-			drop_flag = 1;
+			drop_flag =  1;
 		} else {
 
 			pack = pxe_core_alloc_packet(buffer_size);
@@ -845,6 +844,8 @@
 		}
 	}
 
+	received = frame_size;
+	
 	while (received < buffer_size) {
 
 		if (!pxe_core_get_packet(PXENV_UNDI_ISR_IN_GET_NEXT, undi_isr))
@@ -898,8 +899,9 @@
 	
 	func = PXENV_UNDI_ISR_IN_GET_NEXT;
 
-	if (received == buffer_size)
+/*	if (received == buffer_size)
 		return processed_packets;
+*/
 	    
 	goto packet_start;
 
@@ -1029,6 +1031,13 @@
 	return ns_ip.ip;
 }
 
+void
+pxe_set_nsip32(uint32_t new_ip)
+{
+
+	ns_ip.ip = new_ip;
+}
+
 const MAC_ADDR*
 pxe_get_mymac()
 {

==== //depot/projects/soc2007/taleks-pxe_http/pxe_core.h#10 (text+ko) ====

@@ -118,5 +118,6 @@
 
 /* returns nameserver ip */
 uint32_t pxe_get_nsip32();
+void	 pxe_set_nsip32(uint32_t new_ns);
 
 #endif // PXE_CORE_H_INCLUDED

==== //depot/projects/soc2007/taleks-pxe_http/pxe_dns.c#2 (text+ko) ====

@@ -4,56 +4,375 @@
 #include "pxe_dns.h"
 #include "pxe_sock.h"
 
+/* write_question_for()-  writes labels for provided domain name 
+ * in:
+ *	question - where to write
+ *	name	 - domain name
+ * out:
+ *	NULL	- if failed
+ *	non NULL- ponits to the next byte after labeled name.
+ */
+char *
+write_question_for(uint8_t *question, const char *name) 
+{
+	size_t	len = strlen(name);
+
+	if (len > 255) {	/* oversize */
+		return (NULL);
+	}
+
+	size_t	ind = len;
+	uint8_t	symbol_count = 0;
+	uint8_t	*res = question + len;
+	char	*np = name + len - 1;
+	question[len + 1] = 0; /* label end of question */	
+	
+	/* placing from the end, replacing dots with symbol counter */
+	for ( ; ind != 0; --ind) {
+
+		*res = *np;
+		
+		if ( *res == '.') {
+			
+			if (symbol_count == 0) { /* example..of.error */
+				return (NULL);
+			}
+			
+			*res = symbol_count;
+			symbol_count = 0;
+			
+		} else {
+			++symbol_count;
+		}
+		
+		--res;
+		--np;
+	}
+	
+	*res = symbol_count; /* length for first label */
+		
+	/* +1 for first length, +1 for \0 */
+	return (question + len + 2);
+}
+
+/* create_dns_packet()-  creates DNS request packet 
+ * in:
+ *	name - domain name to resolve
+ *	data - buffer for request packet.
+ *	max_size - size of buffer [NOT IMPLEMENTED]
+ *	id	 - request id to distinguish requests
+ * out:
+ *	0	- failed
+ *	>0	- size of created packet
+ */
 int
-create_dns_packet(char *name, void *data, int max_size) {
+create_dns_packet(char *name, void *data, int max_size, uint16_t id, uint16_t query_type) {
 
 	PXE_DNS_REQUEST_HDR	*request = (PXE_DNS_REQUEST_HDR *)data;
+	uint8_t			*question = (uint8_t *)(data + sizeof(PXE_DNS_REQUEST_HDR));
 	
-	/* data must be set with zeroes, so fill only needed values */	
-	request->id = le2be16(1);
+	pxe_memset(request, 0, sizeof(PXE_DNS_REQUEST_HDR));
+	
+	/* header set with zeroes, so fill only needed values */	
+	request->id = le2be16(id);
 	request->flags = le2be16(PXE_DNS_DEFAULT_FLAGS);
-	request->questions_num = le2be16(1);
+	request->qdcount = le2be16(1);
+	
+	question = write_question_for(question, name);
+	
+	if (question == NULL)	/* failed to write question section */
+		return (0);	/* may be, name size is to big */
+		
+	PXE_DNS_REQUEST_FOOT *foot = (PXE_DNS_REQUEST_FOOT *)question;
+
+	/* finishing creating of packet */ 
+	foot->qtype = le2be16(query_type);
+	foot->qclass = le2be16(PXE_DNS_CLASS_IN);
+	 
+	question += sizeof(PXE_DNS_REQUEST_FOOT);
+	
+	/* return total size of packet */
+	return (((void *)question) - data);
+}
+
+/* skip_name() - gets name from answers
+ * in:
+ *	org - pointer to packet data start
+ *	off - offset to name or part of name to get
+ *	to_place - where to place name. NULL, if not interesting for us
+ * out:
+ *	bytes, read from offset (name definition length)
+ */
+int
+skip_name(uint8_t *org, uint16_t off, uint8_t *to_place)
+{
+	uint8_t	label[64];
+	label[0] = 0;
+	
+	int res =0 ;
+	uint8_t *data = org + off;
+	
+	while (*data != 0) {
+	
+		if (*data < 64) { /* just a label */
+			pxe_memcpy(data + 1, label, *data);
+			label[*data] = 0;
+
+			if (to_place != 0) { /* updating to_pace, if interesting */
+
+				if (to_place[0] != 0) /* add dot, if there is part of name in buffer */
+					strcat((char *)to_place, ".");
+					
+				strcat((char *)to_place, (const char*)label);
+			}
+				
+			res += (1 + *data);
+			data += (1 + *data);
+			
+		} else {/* compression  enabled, this is part of pointer */
+			uint16_t off = (((*data) & 0x3f) << 8) + *(data + 1);
+			skip_name(org, off, to_place);
+			
+			res += 1;
+			break;
+		}
+	}
 	
-	/* TODO: finish it after sleeping. 
-	 * 1. count number of symbols in domain name part betweenn dots
-	 * 2. place name to request
-	 * 3. place query type and class
-	 */
+	res += 1;	/* ending zero skip */
+	return (res);
 }
 
+/* parse_dns_reply() - parses reply from DNS server
+ * in:
+ *	data - pointer to buffer, containing packet data
+ *	size - buffer size
+ *	name - domain name to resolve
+ *	canme - where to store cname if found.
+ * out:
+ *	0 	- parsing failed, or packet has no information about our domain
+ *	ip	- success, 32bit ip4 address 
+ */
 uint32_t
-pxe_gethostbyname(char *name)
+parse_dns_reply(uint8_t* data, int size, char *name, uint16_t id, uint8_t *cname) 
 {
-	/* sanity check */
-	if (name == NULL) {
+	
+	cname[0] = 0;
+	
+	if (size < sizeof(PXE_DNS_REQUEST_HDR) + 8) {	/* too small packet to be with data */
+#ifdef PXE_DEBUG
+		printf("parse_dns_reply(): too small packet.\n");
+#endif
+		return (0);
+	}
+	
+	PXE_DNS_REQUEST_HDR	*hdr = (PXE_DNS_REQUEST_HDR *)data;
+	uint8_t			*answer = data + sizeof(PXE_DNS_REQUEST_HDR);
+	
+	if ( hdr->id != le2be16(id)) { /* wrong id */
+#ifdef PXE_DEBUG
+		printf("parse_dns_reply(): wrong id %d, expected %d.\n", le2be16(hdr->id), id);
+#endif
+		return (0);
+	}
+	
+	uint16_t flags = le2be16(hdr->flags);
+	
+	if ( (flags & 0xf800) != 0x8000) { /* QR != 1 */
+#ifdef PXE_DEBUG
+		printf("parse_dns_reply(): got request. Ignoring it.\n");
+#endif	
 		return (0);
 	}
 
-	int	socket = pxe_socket();
+#ifdef PXE_DEBUG	
+	printf("parse_dns_reply(): query/answer/ns/additional = %d/%d/%d/%d\n",
+	    le2be16(hdr->qdcount), le2be16(hdr->ancount), le2be16(hdr->nscount), le2be16(hdr->arcount)
+	);
+#endif
+	/* getting server return code */
+	int rcode = (flags & 0x000f);
 	
-	if (socket == -1) {
-		printf("pxe_gethostbyname(): failed to create socket.\n");
+	switch(rcode) {
+	case 0: /* good */
+		break;
+	case 1:
+	        printf("parse_dns_reply(): server said format error.\n");
+		return (0);
+		break;
+	case 2:
+	        printf("parse_dns_reply(): server failed.\n");
+		return (0);
+		break;
+	case 3:
+	        printf("parse_dns_reply(): name error, domain not exists?\n");
+		return (0);
+		break;	
+	case 4:
+	        printf("parse_dns_reply(): requested operation not implemented.\n");
+		return (0);
+		break;		
+	case 5:
+	        printf("parse_dns_reply(): access refused.\n");
+		return (0);
+		break;		
+	default:
+	        printf("parse_dns_reply(): don't know nothing about rcode = %d.\n", rcode);
 		return (0);
+		break;
 	}
 	
-	uint8_t	dns_pack[512];
+	/* server reported success */
 	
-	pxe_memset(dns_pack, 0, 512);
+	if (hdr->ancount == 0) { /* there is no answers */
+	        printf("parse_dns_reply(): there are no answers in DNS server reply.\n");
+		return (0);	
+	}
+
+	uint8_t	 aname[256];	/* storage for domain names in answers */
 	
-	int	size = create_dns_packet(name, dns_pack, 512);
+	switch (le2be16(hdr->qdcount)) {
+	case 0:	/* best case, nothing must be skipped to get answer data */
+		break;
+	case 1:
+
+		aname[0] = 0;
+		answer += skip_name(data, answer - data, aname);
+#ifdef PXE_DEBUG
+		printf("question: %s\n", aname);
+#endif		
+		/* answer points to zero, skipping claas/type */
+		answer += sizeof(PXE_DNS_REQUEST_FOOT);
+		break;
 	
-	if (size == 0) {
-		goto ret;	    
+	default: /* error */
+		printf("parse_dns_reply(): me sent only one query, but server says %d.\n", le2be16(hdr->qdcount));
+		return (0);
 	}
 	
-	int	trys = PXE_MAX_DNS_TRYS;
-	int	time = 0;
+	
+	/* parsing answers, authorative section and additional section, hoping to find A resource record */
+	uint16_t index = le2be16(hdr->ancount) + le2be16(hdr->nscount) + le2be16(hdr->arcount);
+	
+	while (index) {
+
+		aname[0] = 0;		
+		answer += skip_name(data, answer - data, aname);
+
+#ifdef PXE_DEBUG
+		printf("answer: %s", aname);	
+#endif		
+		PXE_DNS_REQUEST_FOOT	*ans_foot = (PXE_DNS_REQUEST_FOOT *)answer;
+	
+		if (le2be16(ans_foot->qclass) != PXE_DNS_CLASS_IN) {
+			printf("parse_dns_reply(): IN expected, got 0x%x.\n", le2be16(ans_foot->qclass));
+			return (0);
+		}
+	
+		answer += sizeof(PXE_DNS_REQUEST_FOOT);	
+
+		PXE_DNS_REQUEST_FOOT2	*ans_foot2 = (PXE_DNS_REQUEST_FOOT2 *)answer;
+
+		answer += sizeof(PXE_DNS_REQUEST_FOOT2);
+		
+		uint16_t qtype = le2be16(ans_foot->qtype);
+		uint16_t rdlength = le2be16(ans_foot2->rdlength);
+			
+		if (qtype == PXE_DNS_QUERY_A) {
+			/* successfully got A record */
+			
+			if ( (!strcmp(aname, name)) ||			/* A for our address */
+			     ((cname[0]) && (!strcmp(aname, cname)))	/* A for our CNAME */
+			    ) 
+			
+			{
+				/* sanity check */
+				if (rdlength != 4) { /* wrong length of ip4 adrress length*/
+					return (0);
+				}
+		
+				/* answer points to rdata = ip4 */	
+				PXE_IPADDR ret;
+	
+				ret.octet[0] = answer[0];
+				ret.octet[1] = answer[1];
+				ret.octet[2] = answer[2];
+				ret.octet[3] = answer[3];
+#ifdef PXE_DEBUG
+				printf(" = %d.%d.%d.%d\n",
+				    ret.octet[0], ret.octet[1], ret.octet[2], ret.octet[3]
+				);
+#endif				
+				return ret.ip;
+			}
+
+#ifdef PXE_DEBUG
+			printf("parse_dns_reply(): A resource record '%s' is strange. Ignoring it.\n", aname);
+#endif
+		}
+
+		if (qtype == PXE_DNS_QUERY_CNAME) {
+
+			cname[0] = 0;
+			skip_name(data, answer - data, cname);			
+#ifdef PXE_DEBUG
+			printf(" is alias to %s\n", (char *)cname);
+#endif
+			
+		} else {
+			printf("parse_dns_reply(): A or CNAME expected, but got 0x%x, rdlength: %d.\n", qtype, rdlength);
+		}
+		
+		answer += rdlength;
+		--index;
+	}
+
+	/* have not found anyrhing good */
+	return (0);	
+}
 
+/* pxe_gethostbyname() - returns ip4 address by domain name
+ * in:
+ *	name - domain name to resolve
+ * out:
+ *	0 	- if failed
+ *	ip4addr - if success
+ */
+uint32_t
+pxe_gethostbyname(char *name)
+{
+	/* sanity check */
+	if (name == NULL) {
+		return (0);
+	}
+	
+	/* 512 bytes is limit for packet, sent via UDP */
+	uint8_t	dns_pack[512];
+	uint8_t	cname[256];
+	
+	pxe_memset(dns_pack, 0, 512);
+	
+	int		size = 0;
+	int		trys = PXE_MAX_DNS_TRYS;
+	int		time = 0;
+	uint16_t	id = 1;
 	 
 	while (trys) {
-#ifdef PXE_DEBUG
-		printf("?");
-#endif	
+
+		int	socket = pxe_socket();
+	
+		if (socket == -1) {
+			printf("pxe_gethostbyname(): failed to create socket.\n");
+			return (0);
+		}
+
+
+		size = create_dns_packet(name, dns_pack, 512, id, PXE_DNS_QUERY_A);
+	
+		if (size == 0) {
+			printf("pxe_gethostbyname(): failed to create request.\n");
+			return (0);	    
+		}
+
 		if (size != pxe_sendto(socket, pxe_get_nsip32(), 53,  dns_pack, size)) {
 			printf("pxe_gethostbyname(): failed to send DNS request.\n");
 			pxe_close(socket);
@@ -61,7 +380,7 @@
 		}
 		
 		time = 0;
-
+		
 		while (time < PXE_MAX_DNS_TIMEOUT) {
 		
 			if (!pxe_core_recv_packets()) {
@@ -72,16 +391,42 @@
 			
 			size = pxe_recv(socket, dns_pack, 512);
 			if (size > 0) {
-			    /* TODO: process dns reply */
-			    printf("pxe_gethostbyname(): Received DNS reply (%d bytes).\n", size);
-			    goto ret;
+#ifdef PXE_DEBUG
+				printf("pxe_gethostbyname(): Received DNS reply (%d bytes).\n", size);
+#endif			    
+				uint32_t	res = parse_dns_reply(dns_pack, size, name, id, cname);
+			
+			    	if (res != 0) {
+					pxe_close(socket);
+				        return (res);
+				}
+				
+				pxe_sock_rewind(socket, size); /* NOTE: remove this after normal implementing of sockets */
+
+				if (cname[0] != 0) { /* failed to get A, but found CNAME, need to send other request */
+					
+					size = create_dns_packet(name, dns_pack, 512, id, PXE_DNS_QUERY_CNAME);
+	
+					if (size == 0) {
+						printf("pxe_gethostbyname(): failed to create request.\n");
+						break; /* next try */
+					}
+
+					if (size != pxe_send(socket, dns_pack, size)) {
+						printf("pxe_gethostbyname(): failed to send DNS request.\n");
+						pxe_close(socket);
+						return (0);
+					}			
+				}
+
 			}
 		}
 		
 		trys -= 1;
+		id += 1;
+
+		pxe_close(socket);
 	}
 
-ret:
-	pxe_close(socket);
 	return (0);
 }

==== //depot/projects/soc2007/taleks-pxe_http/pxe_dns.h#2 (text+ko) ====

@@ -3,17 +3,20 @@
 
 #include <stdint.h>
 
+/*
+ * Reference: RFC 1035
+ */
 /* max seconds to wait DNS reply in milliseconds */
 #define PXE_MAX_DNS_TIMEOUT		10000
 /* how many times to try, if there is no reply */
 #define	PXE_MAX_DNS_TRYS		3
-/* query flags */
+/* query flags, set only RecursionDesired bit */
 #define PXE_DNS_DEFAULT_FLAGS		0x0100
 /* query A and CNAME records */
 #define	PXE_DNS_QUERY_A			0x0001
-#define	PXE_DNS_CNAME			0x0005
+#define	PXE_DNS_QUERY_CNAME		0x0005
 /* query class */
-#define	PXE_DNS_CLASS_INET		0x0001
+#define	PXE_DNS_CLASS_IN		0x0001
 
 /* returns ip address by name, or 0 if failed */
 uint32_t  pxe_gethostbyname(char *name);
@@ -21,15 +24,59 @@
 typedef struct pxe_dns_request_hdr {
 	uint16_t	id;	/* query identifier */
 	uint16_t	flags;
-	uint16_t	questions_num;
-	uint16_t	answers_num;
-	uint16_t	auths_num;
-	uint16_t	adds_num;
+
+
+	uint16_t	qdcount; /* number of entries in the question section */
+	uint16_t	ancount; /* number of resource records in the answer section*/
+	uint16_t	nscount; /* name server resource records in the authority
+				  * records section.
+				  */
+	uint16_t	arcount; /* number of resource records in the additional
+				  * records section.
+				  */
 } __packed PXE_DNS_REQUEST_HDR;
 
+/* flags are (copied from RFC 1035):
+ *                                1  1  1  1  1  1
+ *  0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
+ * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ * |QR|   Opcode  |AA|TC|RD|RA|   Z    |   RCODE   |
+ * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ *  QR - 0 for query, 1 for reply
+ *  OPCODE -  kind of query
+ *              0 -  a standard query (QUERY)
+ *              1 -  an inverse query (IQUERY)
+ *              2 -  a server status request (STATUS)
+ *  AA - set if authorative
+ *  TC - set if message truncated
+ *  RD - set if recursion desired
+ *  RA - set if recursion available
+ *  Z  - reserved, must be zeroed
+ *  RCODE - return code:
+ *              0 - no error
+ *              1 - format error
+ *              2 - server failed
+ *              3 - name error
+ *              4 - not implemented
+ *              5 - refused
+ */
+
+/* RCODE values */
+#define PXE_RCODE_NOERROR		0x0
+#define PXE_RCODE_FORMAT_ERROR		0x1
+#define PXE_RCODE_SERVER_FAILED		0x2
+#define PXE_RCODE_NAME_ERROR		0x3
+#define PXE_RCODE_NOT_IMPLEMENTED	0x4
+#define PXE_RCODE_REFUSED		0x5
+
 typedef struct pxe_dns_request_foot {
-	uint16_t	type;
-	uint16_t	class;
-} __packed PXE_FNS_REQUEST_FOOT;
+	uint16_t	qtype;		/* type of query, e.g. A */
+	uint16_t	qclass;		/* class of query, e.g. IN */
+} __packed PXE_DNS_REQUEST_FOOT;
+
+typedef struct pxe_dns_request_foot2 {
+	uint32_t	ttl;		/* seconds answer will be valid to cache */
+	uint16_t	rdlength;	/* length of data, followed by this structure */
+} __packed PXE_DNS_REQUEST_FOOT2;
 
 #endif

==== //depot/projects/soc2007/taleks-pxe_http/pxe_filter.c#2 (text+ko) ====

@@ -47,14 +47,19 @@
 		free_head->prev = NULL;
 		++all_filters;
 	}
-	
+
+#ifdef PXE_DEBUG_HELL
+	printf("_pxe_filter_alloc(): entry = 0x%x, head =  0x%x.\n", res, free_head);
+#endif	
 	return (res);
 }
 
 void
 _pxe_filter_free(PXE_FILTER_ENTRY *entry)
 {
-
+#ifdef PXE_DEBUG_HELL
+	printf("_pxe_filter_free(): entry = 0x%x, head =  0x%x.\n", entry, free_head);
+#endif
 	entry->next = free_head;
 	entry->prev = NULL;
 	
@@ -72,9 +77,14 @@
 PXE_FILTER_ENTRY *
 pxe_filter_add(uint32_t src_ip, uint16_t src_port, uint32_t dst_ip, uint16_t dst_port, void *socket, uint8_t proto)
 {
-
+#ifdef PXE_DEBUG	
+	if (socket == NULL) {
+		printf("pxe_filter_add(): NULL socket.\n");
+		return (NULL);
+	}
+#endif
 	if (free_head == NULL) {
-		printf("pxe_filter_add(): filter table is full.\n");
+		printf("pxe_filter_add(): filter table is full (all_filter = %d).\n", all_filters);
 		return (NULL);	/* there is no space for filters */
 	}
 
@@ -212,6 +222,15 @@
 int
 pxe_filter_remove(PXE_FILTER_ENTRY *filter)
 {
+#ifdef PXE_DEBUG
+    if (filter == NULL) {
+	    printf("pxe_filter_remove(): NULL filter.\n");
+	    return (0);
+    }
+    
+    printf("pxe_filter_remove(): removing filter 0x%x.\n", filter);
+    
+#endif
 
     if (filter != filters_head) { /* non head filter */
 

==== //depot/projects/soc2007/taleks-pxe_http/pxe_sock.c#5 (text+ko) ====

@@ -40,11 +40,12 @@
 
 	sock->state = PXE_SOCKET_FREE;
 	
+/*	NOTE: may be it's not good place for it
 	if (sock->filter) {
 		pxe_filter_remove(sock->filter);
 		sock->filter = NULL;
 	}
-	
+*/	
 	return (1);
 }
 
@@ -58,33 +59,39 @@
 	if (socket == -1)
 		return (-1);
 
+#ifdef PXE_DEBUG
+	printf("pxe_socket(): created socket %d.\n", socket);
+#endif
 	/* creating buffers */
-	PXE_SOCKET	*sock = &pxe_sockets[socket];
+	PXE_BUFFER	*rbuf = &pxe_sockets[socket].recv_buffer;
+	PXE_BUFFER	*sbuf = &pxe_sockets[socket].send_buffer;	
 	
-	sock->send_buffer.data = pxe_alloc(PXE_DEFAULT_SEND_BUFSIZE);
+	sbuf->data = pxe_alloc(PXE_DEFAULT_SEND_BUFSIZE);
 	
-	if (sock->send_buffer.data == NULL) {
+	if (sbuf->data == NULL) {
 	
 		pxe_socket_free(socket);
 		return (-1);
 	}
 	
-	sock->send_buffer.bufsize = PXE_DEFAULT_SEND_BUFSIZE;
-	sock->send_buffer.bufleft = PXE_DEFAULT_SEND_BUFSIZE;
-	sock->send_buffer.next_data = sock->send_buffer.data;
+	sbuf->bufsize = PXE_DEFAULT_SEND_BUFSIZE;
+	sbuf->bufleft = PXE_DEFAULT_SEND_BUFSIZE;
+	sbuf->free_start = sbuf->data;
+	sbuf->free_end = sbuf->data + sbuf->bufsize;
 
-	sock->recv_buffer.data = pxe_alloc(PXE_DEFAULT_RECV_BUFSIZE);
+	rbuf->data = pxe_alloc(PXE_DEFAULT_RECV_BUFSIZE);
 	
-	if (sock->recv_buffer.data == NULL) {
+	if (rbuf->data == NULL) {
 	
-		pxe_free(sock->send_buffer.data);
+		pxe_free(rbuf->data);
 		pxe_socket_free(socket);
 		return (-1);
 	}
 	
-	sock->recv_buffer.bufsize = PXE_DEFAULT_RECV_BUFSIZE;
-	sock->recv_buffer.bufleft = PXE_DEFAULT_RECV_BUFSIZE;	
-	sock->recv_buffer.next_data = sock->recv_buffer.data;
+	rbuf->bufsize = PXE_DEFAULT_RECV_BUFSIZE;
+	rbuf->bufleft = PXE_DEFAULT_RECV_BUFSIZE;	
+	rbuf->free_start = rbuf->data;
+	rbuf->free_end = rbuf->data + rbuf->bufsize;
 	
 	return (socket);		
 }
@@ -92,12 +99,30 @@
 int
 pxe_close(int socket)
 {
+#ifdef PXE_DEBUG
+	printf("pxe_close(): closing socket %d\n", socket);
+#endif	
+	if ( (socket >= PXE_DEFAULT_SOCKETS) || (socket == -1)) {
+		printf("pxe_close(): invalid socket %d\n", socket);
+		return (0);
+	}
+	
+	PXE_SOCKET	*sock = &pxe_sockets[socket];
 
-	if (socket > PXE_DEFAULT_SOCKETS) {
+	if (sock->state == PXE_SOCKET_FREE) {
+#ifdef PXE_DEBUG
+		printf("pxe_close(): socket %d already closed.\n", socket);
+#endif 	
 		return (0);
 	}
 	
-	PXE_SOCKET	*sock = &pxe_sockets[socket];
+	if (sock->filter != NULL)	
+		pxe_filter_remove(sock->filter);
+	else {
+#ifdef PXE_DEBUG
+		printf("pxe_close(): filter for socket already NULL.\n");
+#endif
+	}
 	
 	pxe_free(sock->send_buffer.data);
 	pxe_free(sock->recv_buffer.data);
@@ -115,7 +140,9 @@
 	PXE_FILTER_ENTRY *filter = pxe_filter_add(0, 0, pxe_get_myip32(), port, &pxe_sockets[socket], proto);
 	
 	if (filter == NULL) {
+#ifdef PXE_DEBUG
 		printf("pxe_listen(): failed to add filter.\n");
+#endif
 		return (-1);
 	}
 	
@@ -143,7 +170,7 @@
 pxe_accept(int socket)
 {
 
-	if (socket > PXE_DEFAULT_SOCKETS) {
+	if ( (socket >= PXE_DEFAULT_SOCKETS) || (socket == -1)) {
 		return (-1);
 	}
 	
@@ -196,7 +223,7 @@
 		if (sock->state == PXE_SOCKET_FREE)
 			continue;
 			
-		printf("%d: filter 0x%x, recv/send: %d/%d, waiting: %d.\n ", 
+		printf("%d: filter 0x%x, recv/send: %d/%d, waiting: %d.\n", 
 		    socket, sock->filter, sock->recv, sock->sent, sock->waiting
 		);
 	}
@@ -205,7 +232,7 @@
 int
 pxe_sock_bufspace(int socket)
 {
-	if (socket > PXE_DEFAULT_SOCKETS) {
+	if ( (socket >= PXE_DEFAULT_SOCKETS) || (socket == -1)) {
 		return (-1);
 	}
 	
@@ -215,51 +242,66 @@
 int
 pxe_sock_place(int socket, void* data, uint16_t size)
 {
-#ifdef PXE_DEBUG_HELL
-	printf("pxe_sock_place(): sock: %d, data: 0x%x, size: %d\n", socket, data, size);
+#ifdef PXE_DEBUG
+	printf("pxe_sock_place(): socket: %d, data: 0x%x, size: %d\n", socket, data, size);
 #endif
-	if (socket > PXE_DEFAULT_SOCKETS) {
+	if ( (socket >= PXE_DEFAULT_SOCKETS) || (socket == -1)) {
 		return (-1);
 	}
 	
-	PXE_SOCKET	*sock = &pxe_sockets[socket];
+	PXE_BUFFER	*rbuf = &pxe_sockets[socket].recv_buffer;
 	uint16_t 	copy_size = size;
 	
 	/* there is no enogh space available in recv buffer
 	 *   try as much as possible.
 	 */	
-	if (sock->recv_buffer.bufleft < size) {
+	if (rbuf->bufleft < size) {
 		
-		copy_size = sock->recv_buffer.bufleft;
+		copy_size = rbuf->bufleft;
 		
 		if (copy_size == 0)
 			return (0);
 	}
 		
-	pxe_memcpy(data, sock->recv_buffer.next_data, copy_size);
+	pxe_memcpy(data, rbuf->free_start, copy_size);
 	
-	sock->recv_buffer.next_data += copy_size;
-	sock->recv_buffer.bufleft -= copy_size;
-	
+	rbuf->free_start += copy_size;
+	rbuf->bufleft -= copy_size;
+
+#ifdef PXE_DEBUG
+	printf("pxe_sock_place(): left:  %d\n", rbuf->bufleft);
+#endif	
 	return (copy_size);
 }
 
 int
+pxe_sock_get(PXE_SOCKET *sock)
+{
+	int res = sock - pxe_sockets;
+
+	if (res > PXE_DEFAULT_SOCKETS)
+		return (-1);
+		
+	return (res);
+}
+
+int
 pxe_sock_rewind(int socket, uint16_t size)
 {
-	if (socket > PXE_DEFAULT_SOCKETS) {
+
+	if ( (socket >= PXE_DEFAULT_SOCKETS) || (socket == -1)) {
 		return (-1);
 	}
 	
 	PXE_SOCKET	*sock = &pxe_sockets[socket];
 	
-	uint16_t	rew_bytes = sock->recv_buffer.next_data - sock->recv_buffer.data;
+	uint16_t	rew_bytes = sock->recv_buffer.free_start - sock->recv_buffer.data;
 
 	/* if data to rewind enough, than rewing size, else only available rew_bytes */
 	if (rew_bytes > size)
 		rew_bytes = size;
 
-	sock->recv_buffer.next_data -= rew_bytes;
+	sock->recv_buffer.free_start -= rew_bytes;
 	sock->recv_buffer.bufleft += rew_bytes;
 	
 	return (rew_bytes);
@@ -284,9 +326,6 @@
 pxe_sendto(int socket, uint32_t ip, uint16_t port, void *data, uint16_t size)
 {
 
-#ifdef PXE_DEBUG
-	printf("pxe_sendto(): ip:port =  %8x:%d, size = %d bytes.\n", ip, port, size);
-#endif
 	if (size + sizeof(PXE_UDP_PACKET) > PXE_DEFAULT_SEND_BUFSIZE) {
 		printf("pxe_sendto(): send buffer too small for %d bytes.\n", size);
 		return (-1);
@@ -311,7 +350,11 @@
 	 *  is local port.
 	 */
 	uint16_t lport = filter->dst_port;
-	
+
+#ifdef PXE_DEBUG
+	printf("pxe_sendto(): %8x:%d -> %8x:%d, size = %d bytes.\n", pxe_get_myip32(), lport, ip, port, size);
+#endif	
+
 	if (!pxe_udp_send(udp_pack, ip, port, lport, size + sizeof(PXE_UDP_PACKET), 1)) {
 		printf("pxe_sendto(): failed to send data.\n");
 		return (-1);
@@ -326,7 +369,7 @@
 pxe_connect(int socket, uint32_t ip, uint16_t port, uint8_t proto)
 {
 
-	if (socket > PXE_DEFAULT_SOCKETS) {
+	if ( (socket >= PXE_DEFAULT_SOCKETS) || (socket == -1)) {
 		return (0);
 	}
 	
@@ -355,23 +398,81 @@
 		return (0);	
 	}
 	
+	sock->filter = entry;
+	
 	/* all is ok */
 	return (1);
 }
 
-
+/* assuming socket is UDP, need to think about TCP/UDP functions calling,
+ * also, need to understand how to update buffer for multiple received dgrams

>>> TRUNCATED FOR MAIL (1000 lines) <<<



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200706030952.l539q3eC056262>