PERFORCE change 120824 for review
Alexey Tarasov
taleks at FreeBSD.org
Sun Jun 3 09:52:05 UTC 2007
http://perforce.freebsd.org/chv.cgi?CH=120824
Change 120824 by taleks at 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) <<<
More information about the p4-projects
mailing list