OpenCores
URL https://opencores.org/ocsvn/mlite/mlite/trunk

Subversion Repositories mlite

[/] [mlite/] [trunk/] [kernel/] [tcpip.c] - Blame information for rev 304

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 155 rhoads
/*--------------------------------------------------------------------
2
 * TITLE: Plasma TCP/IP Protocol Stack
3
 * AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4
 * DATE CREATED: 4/22/06
5
 * FILENAME: tcpip.c
6
 * PROJECT: Plasma CPU core
7
 * COPYRIGHT: Software placed into the public domain by the author.
8
 *    Software 'as is' without warranty.  Author liable for nothing.
9
 * DESCRIPTION:
10
 *    Plasma TCP/IP Protocol Stack
11
 *
12
 *    Possible call stack when receiving a packet:
13
 *       IPMainThread()
14
 *          IPProcessEthernetPacket()
15
 *             IPProcessTCPPacket()
16
 *                TCPSendPacket()
17
 *                   IPSendPacket()
18
 *                      IPChecksum()
19
 *                      IPSendFrame()
20
 *                         FrameInsert()
21
 *--------------------------------------------------------------------*/
22
#ifdef WIN32
23
#include <stdio.h>
24
#include <stdlib.h>
25
#include <string.h>
26
#include <assert.h>
27
#define _LIBC
28
#endif
29
#include "rtos.h"
30
#include "tcpip.h"
31
 
32
 
33
//ETHER FIELD                 OFFSET   LENGTH   VALUE
34
#define ETHERNET_DEST         0        //6
35
#define ETHERNET_SOURCE       6        //6
36
#define ETHERNET_FRAME_TYPE   12       //2      IP=0x0800; ARP=0x0806
37
 
38
//ARP   FIELD                 OFFSET   LENGTH   VALUE
39
#define ARP_HARD_TYPE         14       //2      0x0001
40
#define ARP_PROT_TYPE         16       //2      0x0800
41
#define ARP_HARD_SIZE         18       //1      0x06
42
#define ARP_PROT_SIZE         19       //1      0x04
43
#define ARP_OP                20       //2      ARP=1;ARPreply=2
44
#define ARP_ETHERNET_SENDER   22       //6
45
#define ARP_IP_SENDER         28       //4
46
#define ARP_ETHERNET_TARGET   32       //6
47
#define ARP_IP_TARGET         38       //4
48
#define ARP_PAD               42       //18     0
49
 
50
//IP    FIELD                 OFFSET   LENGTH   VALUE
51
#define IP_VERSION_LENGTH     14       //1      0x45
52
#define IP_TYPE_OF_SERVICE    15       //1      0x00
53
#define IP_LENGTH             16       //2
54
#define IP_ID16               18       //2
55
#define IP_FRAG_OFFSET        20       //2
56
#define IP_TIME_TO_LIVE       22       //1      0x80
57
#define IP_PROTOCOL           23       //1      TCP=0x06;PING=0x01;UDP=0x11
58
#define IP_CHECKSUM           24       //2
59
#define IP_SOURCE             26       //4
60
#define IP_DEST               30       //4
61
 
62
//PSEUDO FIELD                OFFSET   LENGTH   VALUE
63
#define PSEUDO_IP_SOURCE      0        //4
64
#define PSEUDO_IP_DEST        4        //4
65
#define PSEUDO_ZERO           8        //1      0
66
#define PSEUDO_IP_PROTOCOL    9        //1
67
#define PSEUDO_LENGTH         10       //2
68
 
69
//UDP   FIELD                 OFFSET   LENGTH   VALUE
70
#define UDP_SOURCE_PORT       34       //2
71
#define UDP_DEST_PORT         36       //2
72
#define UDP_LENGTH            38       //2
73
#define UDP_CHECKSUM          40       //2
74
#define UDP_DATA              42
75
 
76
//DHCP  FIELD                 OFFSET   LENGTH   VALUE
77
#define DHCP_OPCODE           42       //1      REQUEST=1;REPLY=2
78
#define DHCP_HW_TYPE          43       //1      1
79
#define DHCP_HW_LEN           44       //1      6
80
#define DHCP_HOP_COUNT        45       //1      0
81
#define DHCP_TRANS_ID         46       //4
82
#define DHCP_NUM_SEC          50       //2      0
83
#define DHCP_UNUSED           52       //2
84
#define DHCP_CLIENT_IP        54       //4
85
#define DHCP_YOUR_IP          58       //4
86
#define DHCP_SERVER_IP        62       //4
87
#define DHCP_GATEWAY_IP       66       //4
88
#define DHCP_CLIENT_ETHERNET  70       //16
89
#define DHCP_SERVER_NAME      86       //64
90
#define DHCP_BOOT_FILENAME    150      //128
91
#define DHCP_MAGIC_COOKIE     278      //4      0x63825363
92
#define DHCP_OPTIONS          282      //N
93
 
94
#define DHCP_MESSAGE_TYPE     53       //1 type
95
#define DHCP_DISCOVER         1
96
#define DHCP_OFFER            2
97
#define DHCP_REQUEST          3
98
#define DHCP_ACK              5
99
#define DHCP_REQUEST_IP       50       //4 ip
100
#define DHCP_REQUEST_SERV_IP  54       //4 ip
101
#define DHCP_CLIENT_ID        61       //7 1 ethernet
102
#define DHCP_HOST_NAME        12       //6 plasma
103
#define DHCP_PARAMS           55       //4 1=subnet; 15=domain_name; 3=router; 6=dns
104
#define DHCP_PARAM_SUBNET     1
105
#define DHCP_PARAM_ROUTER     3
106
#define DHCP_PARAM_DNS        6
107
#define DHCP_END_OPTION       0xff
108
 
109
//DHCP  FIELD                 OFFSET   LENGTH   VALUE
110 206 rhoads
#define DNS_ID                0        //2    
111
#define DNS_FLAGS             2        //2      
112
#define DNS_NUM_QUESTIONS     4        //2      1 
113
#define DNS_NUM_ANSWERS_RR    6        //2      0/1
114
#define DNS_NUM_AUTHORITY_RR  8        //2      0 
115 155 rhoads
#define DNS_NUM_ADDITIONAL_RR 10       //2      0
116
#define DNS_QUESTIONS         12       //2   
117
 
118
#define DNS_FLAGS_RESPONSE    0x8000
119
#define DNS_FLAGS_RECURSIVE   0x0100
120
#define DNS_FLAGS_ERROR       0x0003
121
#define DNS_FLAGS_OK          0x0000
122
#define DNS_QUERY_TYPE_IP     1
123
#define DNS_QUERY_CLASS       1
124
#define DNS_PORT              53
125
 
126
//TCP   FIELD                 OFFSET   LENGTH   VALUE
127
#define TCP_SOURCE_PORT       34       //2
128
#define TCP_DEST_PORT         36       //2
129
#define TCP_SEQ               38       //4
130
#define TCP_ACK               42       //4
131
#define TCP_HEADER_LENGTH     46       //1      0x50
132
#define TCP_FLAGS             47       //1      SYNC=0x2;ACK=0x10;FIN=0x1
133
#define TCP_WINDOW_SIZE       48       //2
134
#define TCP_CHECKSUM          50       //2
135
#define TCP_URGENT_POINTER    52       //2
136
#define TCP_DATA              54       //length-N
137
 
138
#define TCP_FLAGS_FIN         1
139
#define TCP_FLAGS_SYN         2
140
#define TCP_FLAGS_RST         4
141 209 rhoads
#define TCP_FLAGS_PSH         8
142 155 rhoads
#define TCP_FLAGS_ACK         16
143
 
144
//PING  FIELD                 OFFSET   LENGTH   VALUE
145
#define PING_TYPE             34       //1      SEND=8;REPLY=0
146
#define PING_CODE             35       //1      0
147
#define PING_CHECKSUM         36       //2
148
#define PING_ID               38       //2
149
#define PING_SEQUENCE         40       //2
150
#define PING_DATA             44
151
 
152
static void IPClose2(IPSocket *Socket);
153
 
154
static uint8 ethernetAddressNull[] =    {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
155 206 rhoads
static uint8 ethernetAddressGateway[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
156
#ifndef WIN32
157 155 rhoads
static uint8 ethernetAddressPlasma[] =  {0x00, 0x10, 0xdd, 0xce, 0x15, 0xd4};
158 206 rhoads
#else
159
static uint8 ethernetAddressPlasma[] =  {0x00, 0x10, 0xdd, 0xce, 0x15, 0xd5};
160
#endif
161 155 rhoads
 
162
static uint8 ipAddressPlasma[] =  {0x9d, 0xfe, 0x28, 10};   //changed by DHCP
163
static uint8 ipAddressGateway[] = {0xff, 0xff, 0xff, 0xff}; //changed by DHCP
164
static uint32 ipAddressDns;                                 //changed by DHCP
165
 
166 157 rhoads
static OS_Mutex_t *IPMutex;
167 296 rhoads
static int FrameFreeCount;
168 155 rhoads
static IPFrame *FrameFreeHead;
169
static IPFrame *FrameSendHead;
170
static IPFrame *FrameSendTail;
171
static IPFrame *FrameResendHead;
172
static IPFrame *FrameResendTail;
173
static IPSocket *SocketHead;
174
static uint32 Seconds;
175
static int DhcpRetrySeconds;
176
static IPFuncPtr FrameSendFunc;
177
static OS_MQueue_t *IPMQueue;
178 157 rhoads
static OS_Thread_t *IPThread;
179 155 rhoads
int IPVerbose=1;
180
 
181
static const unsigned char dhcpDiscover[] = {
182
   0xff, 0xff, 0xff, 0xff, 0xff, 0xff,             //dest
183
   0x00, 0x10, 0xdd, 0xce, 0x15, 0xd4,             //src
184
   0x08, 0x00,
185
   0x45, 0x00, 0x01, 0x48, 0x2e, 0xf5, 0x00, 0x00, //ip
186
   0x80, 0x11, 0x0a, 0xb1, 0x00, 0x00, 0x00, 0x00,
187
   0xff, 0xff, 0xff, 0xff,
188
   0x00, 0x44, 0x00, 0x43, 0x01, 0x34, 0x45, 0x66, //udp
189
   0x01, 0x01, 0x06, 0x00, 0x69, 0x26, 0xb5, 0x52  //dhcp
190
};
191
 
192 296 rhoads
static unsigned char dhcpOptions[] = {
193 155 rhoads
   0x63, 0x82, 0x53, 0x63,      //cookie
194
   0x35, 0x01, 0x01,            //DHCP Discover
195
   0x3d, 0x07, 0x01, 0x00, 0x10, 0xdd, 0xce, 0x15, 0xd4, //Client identifier
196 206 rhoads
#ifndef WIN32
197 155 rhoads
   0x0c, 0x06, 'p', 'l', 'a', 's', 'm', 'a',             //Host name
198 206 rhoads
#else
199
   0x0c, 0x06, 'p', 'l', 'a', 's', 'm', 'b',             //Host name
200
#endif
201 155 rhoads
   0x37, 0x03, DHCP_PARAM_SUBNET, DHCP_PARAM_ROUTER, DHCP_PARAM_DNS, //Parameters
202
   DHCP_END_OPTION
203
};
204
 
205
 
206
//Get a free frame; can be called from an ISR
207 157 rhoads
IPFrame *IPFrameGet(int freeCount)
208 155 rhoads
{
209
   IPFrame *frame=NULL;
210
   uint32 state;
211 157 rhoads
 
212
   state = OS_CriticalBegin();
213
   if(FrameFreeCount > freeCount)
214 155 rhoads
   {
215 157 rhoads
      frame = FrameFreeHead;
216
      if(FrameFreeHead)
217 296 rhoads
      {
218 157 rhoads
         FrameFreeHead = FrameFreeHead->next;
219 296 rhoads
         --FrameFreeCount;
220
      }
221 155 rhoads
   }
222 157 rhoads
   OS_CriticalEnd(state);
223 155 rhoads
   if(frame)
224
   {
225 157 rhoads
      assert(frame->state == 0);
226
      frame->state = 1;
227 155 rhoads
   }
228
   return frame;
229
}
230
 
231
 
232
static void FrameFree(IPFrame *frame)
233
{
234
   uint32 state;
235
 
236
   assert(frame->state == 1);
237
   frame->state = 0;
238
   state = OS_CriticalBegin();
239
   frame->next = FrameFreeHead;
240
   FrameFreeHead = frame;
241
   ++FrameFreeCount;
242
   OS_CriticalEnd(state);
243
}
244
 
245
 
246
static void FrameInsert(IPFrame **head, IPFrame **tail, IPFrame *frame)
247
{
248
   assert(frame->state == 1);
249
   frame->state = 2;
250 157 rhoads
   OS_MutexPend(IPMutex);
251 155 rhoads
   frame->prev = NULL;
252
   frame->next = *head;
253
   if(*head)
254
      (*head)->prev = frame;
255
   *head = frame;
256
   if(*tail == NULL)
257
      *tail = frame;
258 157 rhoads
   OS_MutexPost(IPMutex);
259 155 rhoads
}
260
 
261
 
262
static void FrameRemove(IPFrame **head, IPFrame **tail, IPFrame *frame)
263
{
264
   assert(frame->state == 2);
265
   frame->state = 1;
266
   if(frame->prev)
267
      frame->prev->next = frame->next;
268
   else
269
      *head = frame->next;
270
   if(frame->next)
271
      frame->next->prev = frame->prev;
272
   else
273
      *tail = frame->prev;
274
   frame->prev = NULL;
275
   frame->next = NULL;
276
}
277
 
278
 
279
static int IPChecksum(int checksum, const unsigned char *data, int length)
280
{
281
   int i;
282
   checksum = ~checksum & 0xffff;
283
   for(i = 0; i < length-1; i += 2)
284
   {
285
      checksum += (data[i] << 8) | data[i+1];
286
   }
287
   if(i < length)
288
      checksum += data[i] << 8;
289
   while(checksum >> 16)
290
      checksum = (checksum & 0xffff) + (checksum >> 16);
291
   checksum = ~checksum & 0xffff;
292
   return checksum;
293
}
294
 
295
 
296
static int EthernetVerifyChecksums(const unsigned char *packet, int length)
297
{
298
   int checksum, length2;
299
   unsigned char pseudo[12];
300
 
301
   //Calculate checksums
302
   if(packet[ETHERNET_FRAME_TYPE+1] == 0x00)  //IP
303
   {
304
      checksum = IPChecksum(0xffff, packet+IP_VERSION_LENGTH, 20);
305
      if(checksum)
306
         return -1;
307
      if(packet[IP_PROTOCOL] == 0x01)         //PING
308
      {
309
         checksum = IPChecksum(0xffff, packet+PING_TYPE, length-PING_TYPE);
310
      }
311
      else if(packet[IP_PROTOCOL] == 0x11)    //UDP
312
      {
313
         if(packet[UDP_CHECKSUM] == 0 && packet[UDP_CHECKSUM+1] == 0)
314
            return 0;
315
         memcpy(pseudo+PSEUDO_IP_SOURCE, packet+IP_SOURCE, 4);
316
         memcpy(pseudo+PSEUDO_IP_DEST, packet+IP_DEST, 4);
317
         pseudo[PSEUDO_ZERO] = 0;
318
         pseudo[PSEUDO_IP_PROTOCOL] = packet[IP_PROTOCOL];
319
         memcpy(pseudo+PSEUDO_LENGTH, packet+UDP_LENGTH, 2);
320
         checksum = IPChecksum(0xffff, pseudo, 12);
321
         length2 = (packet[UDP_LENGTH] << 8) + packet[UDP_LENGTH+1];
322
         checksum = IPChecksum(checksum, packet+UDP_SOURCE_PORT, length);
323
      }
324
      else if(packet[IP_PROTOCOL] == 0x06)    //TCP
325
      {
326
         memcpy(pseudo+PSEUDO_IP_SOURCE, packet+IP_SOURCE, 4);
327
         memcpy(pseudo+PSEUDO_IP_DEST, packet+IP_DEST, 4);
328
         pseudo[PSEUDO_ZERO] = 0;
329
         pseudo[PSEUDO_IP_PROTOCOL] = packet[IP_PROTOCOL];
330
         length = (packet[IP_LENGTH] << 8) + packet[IP_LENGTH+1];
331
         length2 = length - 20;
332
         pseudo[PSEUDO_LENGTH] = (unsigned char)(length2 >> 8);
333
         pseudo[PSEUDO_LENGTH+1] = (unsigned char)length2;
334
         checksum = IPChecksum(0xffff, pseudo, 12);
335
         checksum = IPChecksum(checksum, packet+TCP_SOURCE_PORT, length2);
336
      }
337
      if(checksum)
338
         return -1;
339
   }
340
   return 0;
341
}
342
 
343
 
344
static void IPFrameReschedule(IPFrame *frame)
345
{
346
   int length;
347
   length = frame->length - TCP_DATA;
348 160 rhoads
   if(frame->packet[TCP_FLAGS] & (TCP_FLAGS_FIN | TCP_FLAGS_SYN))
349 155 rhoads
      ++length;
350
   if(frame->socket == NULL || frame->socket->state == IP_UDP || length == 0 ||
351 209 rhoads
      frame->socket->state == IP_PING || ++frame->retryCnt > 4)
352 155 rhoads
   {
353
      FrameFree(frame);     //can't be ACK'ed
354
   }
355
   else
356
   {
357
      //Put on resend list until TCP ACK'ed
358 296 rhoads
      frame->timeout = RETRANSMIT_TIME * frame->retryCnt;
359 155 rhoads
      FrameInsert(&FrameResendHead, &FrameResendTail, frame);
360
   }
361
}
362
 
363
 
364
static void IPSendFrame(IPFrame *frame)
365
{
366
   uint32 message[4];
367
 
368
   if(FrameSendFunc)
369
   {
370
      //Single threaded
371
      FrameSendFunc(frame->packet, frame->length);
372
      IPFrameReschedule(frame);
373
   }
374
   else
375
   {
376
      //Add Packet to send queue
377
      FrameInsert(&FrameSendHead, &FrameSendTail, frame);
378
 
379
      //Wakeup sender thread
380
      message[0] = 2;
381
      OS_MQueueSend(IPMQueue, message);
382
   }
383
}
384
 
385
 
386
static void IPSendPacket(IPSocket *socket, IPFrame *frame, int length)
387
{
388
   int checksum, length2=length;
389
   unsigned char pseudo[12], *packet=frame->packet;
390
 
391
   frame->length = (uint16)length;
392
 
393
   //Calculate checksums
394
   if(packet[ETHERNET_FRAME_TYPE+1] == 0x00)  //IP
395
   {
396
      length2 = length - IP_VERSION_LENGTH;
397
      packet[IP_LENGTH] = (uint8)(length2 >> 8);
398
      packet[IP_LENGTH+1] = (uint8)length2;
399
      memset(packet+IP_CHECKSUM, 0, 2);
400
      checksum = IPChecksum(0xffff, packet+IP_VERSION_LENGTH, 20);
401
      packet[IP_CHECKSUM] = (unsigned char)(checksum >> 8);
402
      packet[IP_CHECKSUM+1] = (unsigned char)checksum;
403 220 rhoads
      if(packet[IP_PROTOCOL] == 0x01)         //ICMP & PING
404 155 rhoads
      {
405
         memset(packet+PING_CHECKSUM, 0, 2);
406
         checksum = IPChecksum(0xffff, packet+PING_TYPE, length-PING_TYPE);
407
         packet[PING_CHECKSUM] = (unsigned char)(checksum >> 8);
408
         packet[PING_CHECKSUM+1] = (unsigned char)checksum;
409
      }
410
      else if(packet[IP_PROTOCOL] == 0x11)    //UDP
411
      {
412
         length2 = length - UDP_SOURCE_PORT;
413
         packet[UDP_LENGTH] = (uint8)(length2 >> 8);
414
         packet[UDP_LENGTH+1] = (uint8)length2;
415
         memcpy(pseudo+PSEUDO_IP_SOURCE, packet+IP_SOURCE, 4);
416
         memcpy(pseudo+PSEUDO_IP_DEST, packet+IP_DEST, 4);
417
         pseudo[PSEUDO_ZERO] = 0;
418
         pseudo[PSEUDO_IP_PROTOCOL] = packet[IP_PROTOCOL];
419
         memcpy(pseudo+PSEUDO_LENGTH, packet+UDP_LENGTH, 2);
420
         checksum = IPChecksum(0xffff, pseudo, 12);
421
         memset(packet+UDP_CHECKSUM, 0, 2);
422
         length2 = (packet[UDP_LENGTH] << 8) + packet[UDP_LENGTH+1];
423
         checksum = IPChecksum(checksum, packet+UDP_SOURCE_PORT, length2);
424
         packet[UDP_CHECKSUM] = (unsigned char)(checksum >> 8);
425
         packet[UDP_CHECKSUM+1] = (unsigned char)checksum;
426
      }
427
      else if(packet[IP_PROTOCOL] == 0x06)    //TCP
428
      {
429
         memcpy(pseudo+PSEUDO_IP_SOURCE, packet+IP_SOURCE, 4);
430
         memcpy(pseudo+PSEUDO_IP_DEST, packet+IP_DEST, 4);
431
         pseudo[PSEUDO_ZERO] = 0;
432
         pseudo[PSEUDO_IP_PROTOCOL] = packet[IP_PROTOCOL];
433
         length2 = (packet[IP_LENGTH] << 8) + packet[IP_LENGTH+1];
434
         length2 = length2 - 20;
435
         pseudo[PSEUDO_LENGTH] = (unsigned char)(length2 >> 8);
436
         pseudo[PSEUDO_LENGTH+1] = (unsigned char)length2;
437
         checksum = IPChecksum(0xffff, pseudo, 12);
438
         memset(packet+TCP_CHECKSUM, 0, 2);
439
         checksum = IPChecksum(checksum, packet+TCP_SOURCE_PORT, length2);
440
         packet[TCP_CHECKSUM] = (unsigned char)(checksum >> 8);
441
         packet[TCP_CHECKSUM+1] = (unsigned char)checksum;
442
      }
443
   }
444
 
445 160 rhoads
   length2 = length - TCP_DATA;
446
   if(socket && (packet[TCP_FLAGS] & (TCP_FLAGS_FIN | TCP_FLAGS_SYN)))
447 155 rhoads
      length2 = 1;
448
   frame->socket = socket;
449
   frame->timeout = 0;
450
   frame->retryCnt = 0;
451
   if(socket)
452
      frame->seqEnd = socket->seq + length2;
453
   IPSendFrame(frame);
454
}
455
 
456
 
457
static void TCPSendPacket(IPSocket *socket, IPFrame *frame, int length)
458
{
459
   uint8 *packet = frame->packet;
460 160 rhoads
   int flags, count;
461 155 rhoads
 
462
   flags = packet[TCP_FLAGS];
463
   memcpy(packet, socket->headerSend, TCP_SEQ);
464 220 rhoads
   packet[TCP_FLAGS] = (uint8)flags;
465 155 rhoads
   if(flags & TCP_FLAGS_SYN)
466
      packet[TCP_HEADER_LENGTH] = 0x60;  //set maximum segment size
467
   else
468
      packet[TCP_HEADER_LENGTH] = 0x50;
469
   packet[TCP_SEQ]   = (uint8)(socket->seq >> 24);
470
   packet[TCP_SEQ+1] = (uint8)(socket->seq >> 16);
471
   packet[TCP_SEQ+2] = (uint8)(socket->seq >> 8);
472
   packet[TCP_SEQ+3] = (uint8)socket->seq;
473
   packet[TCP_ACK]   = (uint8)(socket->ack >> 24);
474
   packet[TCP_ACK+1] = (uint8)(socket->ack >> 16);
475
   packet[TCP_ACK+2] = (uint8)(socket->ack >> 8);
476
   packet[TCP_ACK+3] = (uint8)socket->ack;
477 160 rhoads
   count = FrameFreeCount - FRAME_COUNT_WINDOW;
478
   if(count < 1)
479
      count = 1;
480 165 rhoads
   if(count > 4)
481
      count = 4;
482 160 rhoads
   count *= 512;
483
   packet[TCP_WINDOW_SIZE] = (uint8)(count >> 8);
484
   packet[TCP_WINDOW_SIZE+1] = (uint8)count;
485 155 rhoads
   packet[TCP_URGENT_POINTER] = 0;
486
   packet[TCP_URGENT_POINTER+1] = 0;
487
   IPSendPacket(socket, frame, length);
488
}
489
 
490
 
491
static void EthernetCreateResponse(unsigned char *packetOut,
492
                                   const unsigned char *packet,
493
                                   int length)
494
{
495
   //Swap destination and source fields
496
   memcpy(packetOut, packet, length);
497
   memcpy(packetOut+ETHERNET_DEST, packet+ETHERNET_SOURCE, 6);
498
   memcpy(packetOut+ETHERNET_SOURCE, packet+ETHERNET_DEST, 6);
499
   if(packet[ETHERNET_FRAME_TYPE+1] == 0x00)  //IP
500
   {
501
      memcpy(packetOut+IP_SOURCE, packet+IP_DEST, 4);
502
      memcpy(packetOut+IP_DEST, packet+IP_SOURCE, 4);
503
      if(packet[IP_PROTOCOL] == 0x06 || packet[IP_PROTOCOL] == 0x11)   //TCP/UDP
504
      {
505
         memcpy(packetOut+TCP_SOURCE_PORT, packet+TCP_DEST_PORT, 2);
506
         memcpy(packetOut+TCP_DEST_PORT, packet+TCP_SOURCE_PORT, 2);
507
      }
508
   }
509
}
510
 
511
 
512
static void IPDhcp(const unsigned char *packet, int length, int state)
513
{
514
   uint8 *packetOut, *ptr;
515
   const uint8 *ptr2;
516
   IPFrame *frame;
517
   static int request=0;
518
 
519
   if(state == 1)
520
   {
521
      //Create DHCP Discover
522 157 rhoads
      frame = IPFrameGet(0);
523 155 rhoads
      if(frame == NULL)
524
         return;
525
      packetOut = frame->packet;
526
      memset(packetOut, 0, 512);
527
      memcpy(packetOut, dhcpDiscover, sizeof(dhcpDiscover));
528
      memcpy(packetOut+ETHERNET_SOURCE, ethernetAddressPlasma, 6);
529
      memcpy(packetOut+DHCP_CLIENT_ETHERNET, ethernetAddressPlasma, 6);
530
      memcpy(packetOut+DHCP_MAGIC_COOKIE, dhcpOptions, sizeof(dhcpOptions));
531
      memcpy(packetOut+DHCP_MAGIC_COOKIE+10, ethernetAddressPlasma, 6);
532
      IPSendPacket(NULL, frame, 400);
533
      request = DHCP_DISCOVER;
534 296 rhoads
      DhcpRetrySeconds = 2;
535 155 rhoads
   }
536
   else if(state == 2 && memcmp(packet+DHCP_CLIENT_ETHERNET, ethernetAddressPlasma, 6) == 0)
537
   {
538
      if(packet[DHCP_MAGIC_COOKIE+6] == DHCP_OFFER && request == DHCP_DISCOVER)
539
      {
540
         //Process DHCP Offer and send DHCP Request
541 157 rhoads
         frame = IPFrameGet(0);
542 155 rhoads
         if(frame == NULL)
543
            return;
544
         packetOut = frame->packet;
545
         memset(packetOut, 0, 512);
546
         memcpy(packetOut, dhcpDiscover, sizeof(dhcpDiscover));
547
         memcpy(packetOut+ETHERNET_SOURCE, ethernetAddressPlasma, 6);
548
         memcpy(packetOut+DHCP_CLIENT_ETHERNET, ethernetAddressPlasma, 6);
549
         memcpy(packetOut+DHCP_MAGIC_COOKIE, dhcpOptions, sizeof(dhcpOptions));
550 206 rhoads
         memcpy(packetOut+DHCP_MAGIC_COOKIE+10, ethernetAddressPlasma, 6);
551 155 rhoads
         request = DHCP_REQUEST;
552
         packetOut[DHCP_MAGIC_COOKIE+6] = DHCP_REQUEST;
553
         ptr = packetOut+DHCP_MAGIC_COOKIE+sizeof(dhcpOptions)-1;
554
         ptr[0] = DHCP_REQUEST_IP;
555
         ptr[1] = 4;
556
         memcpy(ptr+2, packet+DHCP_YOUR_IP, 4);
557
         ptr[6] = DHCP_REQUEST_SERV_IP;
558
         ptr[7] = 4;
559
         memcpy(ptr+8, packet+DHCP_SERVER_IP, 4);
560
         ptr[12] = DHCP_END_OPTION;
561
         IPSendPacket(NULL, frame, 400);
562
      }
563
      else if(packet[DHCP_MAGIC_COOKIE+6] == DHCP_ACK && request == DHCP_REQUEST)
564
      {
565
         //Process DHCP Ack
566
         request = 0;
567
         DhcpRetrySeconds = 3600*4;
568
         memcpy(ipAddressPlasma, packet+DHCP_YOUR_IP, 4);
569
         printf("IP=%d.%d.%d.%d ", ipAddressPlasma[0], ipAddressPlasma[1],
570
            ipAddressPlasma[2], ipAddressPlasma[3]);
571
         memcpy(ipAddressGateway, packet+DHCP_GATEWAY_IP, 4);
572
         if(ipAddressGateway[0] == 0 && ipAddressGateway[1] == 0 &&
573
            ipAddressGateway[2] == 0 && ipAddressGateway[3] == 0)
574
            memcpy(ipAddressGateway, packet+DHCP_SERVER_IP, 4);
575
         printf("GW=%d.%d.%d.%d ", ipAddressGateway[0], ipAddressGateway[1],
576
            ipAddressGateway[2], ipAddressGateway[3]);
577
         memcpy(ethernetAddressGateway, packet+ETHERNET_SOURCE, 6);
578
         ptr2 = packet+DHCP_MAGIC_COOKIE+4;
579
         while(ptr2[0] != DHCP_END_OPTION && (int)(ptr2 - packet) < length)
580
         {
581
            if(ptr2[0] == DHCP_PARAM_DNS)
582
            {
583
               ipAddressDns = (ptr2[2] << 24) | (ptr2[3] << 16) | (ptr2[4] << 8) | ptr2[5];
584
               printf("DNS=%d.%d.%d.%d ", ptr2[2], ptr2[3], ptr2[4], ptr2[5]);
585
            }
586
            ptr2 += ptr2[1] + 2;
587
         }
588
 
589
         //Check if DHCP reply came from gateway
590
         if(memcmp(packet+IP_SOURCE, ipAddressGateway, 4))
591
         {
592
            //Send ARP to gateway
593 157 rhoads
            frame = IPFrameGet(0);
594 155 rhoads
            if(frame == NULL)
595
               return;
596
            packetOut = frame->packet;
597
            memset(packetOut, 0, 512);
598
            memset(packetOut+ETHERNET_DEST, 0xff, 6);
599
            memcpy(packetOut+ETHERNET_SOURCE, ethernetAddressPlasma, 6);
600
            packetOut[ETHERNET_FRAME_TYPE] = 0x08;
601
            packetOut[ETHERNET_FRAME_TYPE+1] = 0x06;
602
            packetOut[ARP_HARD_TYPE+1] = 0x01;
603
            packetOut[ARP_PROT_TYPE] = 0x08;
604
            packetOut[ARP_HARD_SIZE] = 0x06;
605
            packetOut[ARP_PROT_SIZE] = 0x04;
606
            packetOut[ARP_OP+1] = 1;
607
            memcpy(packetOut+ARP_ETHERNET_SENDER, ethernetAddressPlasma, 6);
608
            memcpy(packetOut+ARP_IP_SENDER, ipAddressPlasma, 4);
609
            memcpy(packetOut+ARP_IP_TARGET, ipAddressGateway, 4);
610
            IPSendPacket(NULL, frame, 60);
611
         }
612
      }
613
   }
614
}
615
 
616
 
617 209 rhoads
uint32 IPAddressSelf(void)
618
{
619
   return (ipAddressPlasma[0] << 24) | (ipAddressPlasma[1] << 16) |
620
          (ipAddressPlasma[2] << 8) | ipAddressPlasma[3];
621
}
622
 
623
 
624 155 rhoads
static int IPProcessTCPPacket(IPFrame *frameIn)
625
{
626
   uint32 seq, ack;
627 304 rhoads
   int length, ip_length, bytes, rc=0, notify=0;
628 155 rhoads
   IPSocket *socket, *socketNew;
629
   IPFrame *frameOut, *frame2, *framePrev;
630
   uint8 *packet, *packetOut;
631
 
632
   packet = frameIn->packet;
633
   length = frameIn->length;
634
 
635
   ip_length = (packet[IP_LENGTH] << 8) | packet[IP_LENGTH+1];
636
   seq = (packet[TCP_SEQ] << 24) | (packet[TCP_SEQ+1] << 16) |
637
         (packet[TCP_SEQ+2] << 8) | packet[TCP_SEQ+3];
638
   ack = (packet[TCP_ACK] << 24) | (packet[TCP_ACK+1] << 16) |
639
         (packet[TCP_ACK+2] << 8) | packet[TCP_ACK+3];
640
 
641
   //Check if start of connection
642 160 rhoads
   if((packet[TCP_FLAGS] & (TCP_FLAGS_SYN | TCP_FLAGS_ACK)) == TCP_FLAGS_SYN)
643 155 rhoads
   {
644
      if(IPVerbose)
645
         printf("S");
646
      //Check if duplicate SYN
647
      for(socket = SocketHead; socket; socket = socket->next)
648
      {
649
         if(socket->state != IP_LISTEN &&
650
            packet[IP_PROTOCOL] == socket->headerRcv[IP_PROTOCOL] &&
651
            memcmp(packet+IP_SOURCE, socket->headerRcv+IP_SOURCE, 8) == 0 &&
652
            memcmp(packet+TCP_SOURCE_PORT, socket->headerRcv+TCP_SOURCE_PORT, 4) == 0)
653
         {
654
            if(IPVerbose)
655
               printf("s");
656
            return 0;
657
         }
658
      }
659
 
660
      //Find an open port
661
      for(socket = SocketHead; socket; socket = socket->next)
662
      {
663
         if(socket->state == IP_LISTEN &&
664
            packet[IP_PROTOCOL] == socket->headerRcv[IP_PROTOCOL] &&
665
            memcmp(packet+TCP_DEST_PORT, socket->headerRcv+TCP_DEST_PORT, 2) == 0)
666
         {
667
            //Create a new socket
668 174 rhoads
            frameOut = IPFrameGet(FRAME_COUNT_SYNC);
669 155 rhoads
            if(frameOut == NULL)
670
               return 0;
671
            socketNew = (IPSocket*)malloc(sizeof(IPSocket));
672
            if(socketNew == NULL)
673
               return 0;
674
            memcpy(socketNew, socket, sizeof(IPSocket));
675
            socketNew->state = IP_TCP;
676 296 rhoads
            socketNew->timeout = SOCKET_TIMEOUT;
677 155 rhoads
            socketNew->ack = seq;
678
            socketNew->seq = socketNew->ack + 0x12345678;
679
            socketNew->seqReceived = socketNew->seq;
680
 
681
            //Send ACK
682
            packetOut = frameOut->packet;
683
            EthernetCreateResponse(packetOut, packet, length);
684
            memcpy(socketNew->headerRcv, packet, TCP_SEQ);
685
            memcpy(socketNew->headerSend, packetOut, TCP_SEQ);
686
            packetOut[TCP_FLAGS] = TCP_FLAGS_SYN | TCP_FLAGS_ACK;
687
            ++socketNew->ack;
688
            packetOut[TCP_DATA] = 2;    //maximum segment size = 536
689
            packetOut[TCP_DATA+1] = 4;
690
            packetOut[TCP_DATA+2] = 2;
691
            packetOut[TCP_DATA+3] = 24;
692
            TCPSendPacket(socketNew, frameOut, TCP_DATA+4);
693
            ++socketNew->seq;
694
 
695
            //Add socket to linked list
696 157 rhoads
            OS_MutexPend(IPMutex);
697 155 rhoads
            socketNew->next = SocketHead;
698
            socketNew->prev = NULL;
699
            if(SocketHead)
700
               SocketHead->prev = socketNew;
701
            SocketHead = socketNew;
702 157 rhoads
            OS_MutexPost(IPMutex);
703 304 rhoads
            if(socketNew->funcPtr)
704
               OS_Job(socketNew->funcPtr, socketNew, 0, 0);
705 155 rhoads
            return 0;
706
         }
707
      }
708 220 rhoads
 
709
      //Send reset
710
      frameOut = IPFrameGet(0);
711
      if(frameOut == NULL)
712
         return 0;
713
      packetOut = frameOut->packet;
714
      EthernetCreateResponse(packetOut, packet, TCP_DATA);
715
      memset(packetOut+TCP_SEQ, 0, 4);
716
      ++seq;
717
      packetOut[TCP_ACK]   = (uint8)(seq >> 24);
718
      packetOut[TCP_ACK+1] = (uint8)(seq >> 16);
719
      packetOut[TCP_ACK+2] = (uint8)(seq >> 8);
720
      packetOut[TCP_ACK+3] = (uint8)seq;
721
      packetOut[TCP_HEADER_LENGTH] = 0x50;
722
      packetOut[TCP_FLAGS] = TCP_FLAGS_RST;
723
      IPSendPacket(NULL, frameOut, TCP_DATA);
724 155 rhoads
      return 0;
725
   }
726
 
727
   //Find an open socket
728
   for(socket = SocketHead; socket; socket = socket->next)
729
   {
730
      if(packet[IP_PROTOCOL] == socket->headerRcv[IP_PROTOCOL] &&
731
         memcmp(packet+IP_SOURCE, socket->headerRcv+IP_SOURCE, 8) == 0 &&
732
         memcmp(packet+TCP_SOURCE_PORT, socket->headerRcv+TCP_SOURCE_PORT, 4) == 0)
733
      {
734
         break;
735
      }
736
   }
737
   if(socket == NULL)
738 220 rhoads
   {
739 155 rhoads
      return 0;
740 220 rhoads
   }
741 155 rhoads
 
742 225 rhoads
   //Check if packets can be removed from retransmition list
743
   if(packet[TCP_FLAGS] & TCP_FLAGS_ACK)
744 155 rhoads
   {
745
      if(ack != socket->seqReceived)
746
      {
747 157 rhoads
         OS_MutexPend(IPMutex);
748 155 rhoads
         for(frame2 = FrameResendHead; frame2; )
749
         {
750
            framePrev = frame2;
751
            frame2 = frame2->next;
752
            if(framePrev->socket == socket && (int)(ack - framePrev->seqEnd) >= 0)
753
            {
754
               //Remove packet from retransmition queue
755 160 rhoads
               if(socket->timeout)
756 231 rhoads
                  socket->timeout = socket->timeoutReset;
757 155 rhoads
               FrameRemove(&FrameResendHead, &FrameResendTail, framePrev);
758
               FrameFree(framePrev);
759
            }
760
         }
761 157 rhoads
         OS_MutexPost(IPMutex);
762 155 rhoads
         socket->seqReceived = ack;
763
      }
764 225 rhoads
   }
765 155 rhoads
 
766 225 rhoads
   bytes = ip_length - (TCP_DATA - IP_VERSION_LENGTH);
767 155 rhoads
 
768 225 rhoads
   //Check if SYN/ACK
769
   if((packet[TCP_FLAGS] & (TCP_FLAGS_SYN | TCP_FLAGS_ACK)) ==
770
      (TCP_FLAGS_SYN | TCP_FLAGS_ACK))
771
   {
772
      //Ack SYN/ACK
773
      socket->ack = seq + 1;
774
      frameOut = IPFrameGet(FRAME_COUNT_SEND);
775
      if(frameOut)
776 160 rhoads
      {
777 225 rhoads
         frameOut->packet[TCP_FLAGS] = TCP_FLAGS_ACK;
778
         TCPSendPacket(socket, frameOut, TCP_DATA);
779 160 rhoads
      }
780 225 rhoads
      if(socket->funcPtr)
781
         OS_Job(socket->funcPtr, socket, 0, 0);
782
      return 0;
783
   }
784
   if(packet[TCP_HEADER_LENGTH] != 0x50)
785
   {
786
      if(IPVerbose)
787
         printf("length error\n");
788
      return 0;
789
   }
790
 
791 257 rhoads
   //Check if RST flag set
792
   if(packet[TCP_FLAGS] & TCP_FLAGS_RST)
793
   {
794 304 rhoads
      notify = 1;
795 257 rhoads
      if(socket->state == IP_FIN_SERVER)
796
         IPClose2(socket);
797
      else if(socket->state == IP_TCP)
798
         socket->state = IP_FIN_CLIENT;
799
   }
800 225 rhoads
   //Copy packet into socket
801 257 rhoads
   else if(socket->ack == seq && bytes > 0)
802 225 rhoads
   {
803
      //Insert packet into socket linked list
804 304 rhoads
      notify = 1;
805 225 rhoads
      if(socket->timeout)
806 231 rhoads
         socket->timeout = socket->timeoutReset;
807 225 rhoads
      if(IPVerbose)
808
         printf("D");
809
      if(frameIn->length > ip_length + IP_VERSION_LENGTH)
810 231 rhoads
         frameIn->length = (uint16)(ip_length + IP_VERSION_LENGTH);
811 225 rhoads
      FrameInsert(&socket->frameReadHead, &socket->frameReadTail, frameIn);
812
      socket->ack += bytes;
813
 
814
      //Ack data
815
      frameOut = IPFrameGet(FRAME_COUNT_SEND);
816
      if(frameOut)
817 160 rhoads
      {
818 225 rhoads
         frameOut->packet[TCP_FLAGS] = TCP_FLAGS_ACK;
819
         TCPSendPacket(socket, frameOut, TCP_DATA);
820 160 rhoads
      }
821
 
822 225 rhoads
      //Determine window
823
      socket->seqWindow = (packet[TCP_WINDOW_SIZE] << 8) | packet[TCP_WINDOW_SIZE+1];
824
      if(socket->seqWindow < 8)
825
         socket->seqWindow = 8;
826
 
827
      //Using frame
828
      rc = 1;
829
   }
830
   else if(bytes)
831
   {
832
      //Ack with current offset since data missing
833
      frameOut = IPFrameGet(FRAME_COUNT_SEND);
834
      if(frameOut)
835 155 rhoads
      {
836 225 rhoads
         frameOut->packet[TCP_FLAGS] = TCP_FLAGS_ACK;
837
         TCPSendPacket(socket, frameOut, TCP_DATA);
838
      }
839
   }
840 155 rhoads
 
841 225 rhoads
   //Check if FIN flag set
842
   if(packet[TCP_FLAGS] & TCP_FLAGS_FIN)
843
   {
844 304 rhoads
      notify = 1;
845 225 rhoads
      socket->timeout = SOCKET_TIMEOUT;
846
      if(IPVerbose)
847
         printf("F");
848
      frameOut = IPFrameGet(0);
849
      if(frameOut == NULL)
850
         return 0;
851
      packetOut = frameOut->packet;
852
      packetOut[TCP_FLAGS] = TCP_FLAGS_ACK;
853
      ++socket->ack;
854
      TCPSendPacket(socket, frameOut, TCP_DATA);
855
      if(socket->state == IP_FIN_SERVER)
856
         IPClose2(socket);
857 231 rhoads
      else if(socket->state == IP_TCP)
858 225 rhoads
         socket->state = IP_FIN_CLIENT;
859
   }
860 155 rhoads
 
861 225 rhoads
   //Notify application
862 304 rhoads
   if(socket->funcPtr && notify)
863 225 rhoads
      OS_Job(socket->funcPtr, socket, 0, 0);
864
   return rc;
865 155 rhoads
}
866
 
867
 
868 247 rhoads
int IPProcessEthernetPacket(IPFrame *frameIn, int length)
869 155 rhoads
{
870
   int ip_length, rc;
871
   IPSocket *socket;
872
   IPFrame *frameOut;
873
   uint8 *packet, *packetOut;
874
 
875
   packet = frameIn->packet;
876 247 rhoads
   frameIn->length = (uint16)length;
877 155 rhoads
 
878
   if(packet[ETHERNET_FRAME_TYPE] != 0x08 || frameIn->length > PACKET_SIZE)
879
      return 0;  //wrong ethernet type, packet not used
880
 
881
   //ARP?
882
   if(packet[ETHERNET_FRAME_TYPE+1] == 0x06)
883
   {
884
      //Check if ARP reply
885
      if(memcmp(packet+ETHERNET_DEST, ethernetAddressPlasma, 6) == 0 &&
886
         packet[ARP_OP+1] == 2 && memcmp(packet+ARP_IP_SENDER, ipAddressGateway, 4) == 0)
887
      {
888
         //Found MAC address for gateway
889
         memcpy(ethernetAddressGateway, packet+ARP_ETHERNET_SENDER, 6);
890
         return 0;
891
      }
892
 
893
      //Check if ARP request
894
      if(memcmp(packet+ETHERNET_DEST, ethernetAddressNull, 6) ||
895
         packet[ARP_OP] != 0 || packet[ARP_OP+1] != 1 ||
896
         memcmp(packet+ARP_IP_TARGET, ipAddressPlasma, 4))
897
         return 0;
898
      //Create ARP response
899 157 rhoads
      frameOut = IPFrameGet(0);
900 155 rhoads
      if(frameOut == NULL)
901
         return 0;
902
      packetOut = frameOut->packet;
903
      memcpy(packetOut, packet, frameIn->length);
904
      memcpy(packetOut+ETHERNET_DEST, packet+ETHERNET_SOURCE, 6);
905
      memcpy(packetOut+ETHERNET_SOURCE, ethernetAddressPlasma, 6);
906
      packetOut[ARP_OP+1] = 2; //ARP reply
907
      memcpy(packetOut+ARP_ETHERNET_SENDER, ethernetAddressPlasma, 6);
908
      memcpy(packetOut+ARP_IP_SENDER, packet+ARP_IP_TARGET, 4);
909
      memcpy(packetOut+ARP_ETHERNET_TARGET, packet+ARP_ETHERNET_SENDER, 6);
910
      memcpy(packetOut+ARP_IP_TARGET, packet+ARP_IP_SENDER, 4);
911
      IPSendPacket(NULL, frameOut, frameIn->length);
912
      return 0;
913
   }
914
 
915
   //Check if proper type of packet
916
   ip_length = (packet[IP_LENGTH] << 8) | packet[IP_LENGTH+1];
917
   if(frameIn->length < UDP_DATA || ip_length > frameIn->length - IP_VERSION_LENGTH)
918
      return 0;
919
   if(packet[ETHERNET_FRAME_TYPE+1] != 0x00 ||
920
      packet[IP_VERSION_LENGTH] != 0x45)
921
      return 0;
922
 
923
   //Check if DHCP reply
924
   if(packet[IP_PROTOCOL] == 0x11 &&
925
      packet[UDP_SOURCE_PORT] == 0 && packet[UDP_SOURCE_PORT+1] == 67 &&
926
      packet[UDP_DEST_PORT] == 0 && packet[UDP_DEST_PORT+1] == 68)
927
   {
928
      IPDhcp(packet, frameIn->length, 2);            //DHCP reply
929
      return 0;
930
   }
931
 
932
   //Check if correct destination address
933
   if(memcmp(packet+ETHERNET_DEST, ethernetAddressPlasma, 6) ||
934
      memcmp(packet+IP_DEST, ipAddressPlasma, 4))
935
      return 0;
936
   rc = EthernetVerifyChecksums(packet, frameIn->length);
937
   //if(rc)
938
   //{
939
   //   printf("C ");
940
   //   return;
941
   //}
942
 
943
   //PING request?
944
   if(packet[IP_PROTOCOL] == 1)
945
   {
946 209 rhoads
      if(packet[PING_TYPE] == 0)  //PING reply
947
      {
948
         for(socket = SocketHead; socket; socket = socket->next)
949
         {
950
            if(socket->state == IP_PING &&
951
               memcmp(packet+IP_SOURCE, socket->headerSend+IP_DEST, 4) == 0)
952
            {
953 225 rhoads
               OS_Job(socket->funcPtr, socket, 0, 0);
954 209 rhoads
               return 0;
955
            }
956
         }
957
      }
958 155 rhoads
      if(packet[PING_TYPE] != 8)
959
         return 0;
960 160 rhoads
      frameOut = IPFrameGet(FRAME_COUNT_SEND);
961 155 rhoads
      if(frameOut == NULL)
962
         return 0;
963
      packetOut = frameOut->packet;
964
      EthernetCreateResponse(packetOut, packet, frameIn->length);
965
      frameOut->packet[PING_TYPE] = 0;       //PING reply
966
      IPSendPacket(NULL, frameOut, frameIn->length);
967
      return 0;
968
   }
969
 
970
   //TCP packet?
971
   if(packet[IP_PROTOCOL] == 0x06)
972
   {
973
      return IPProcessTCPPacket(frameIn);
974
   }
975
 
976
   //UDP packet?
977
   if(packet[IP_PROTOCOL] == 0x11)
978
   {
979
      //Find open socket
980
      for(socket = SocketHead; socket; socket = socket->next)
981
      {
982
         if(packet[IP_PROTOCOL] == socket->headerRcv[IP_PROTOCOL] &&
983
            memcmp(packet+IP_SOURCE, socket->headerRcv+IP_SOURCE, 8) == 0 &&
984
            memcmp(packet+UDP_SOURCE_PORT, socket->headerRcv+UDP_SOURCE_PORT, 2) == 0)
985
         {
986
            break;
987
         }
988
      }
989
 
990
      if(socket == NULL)
991
      {
992
         //Find listening socket
993
         for(socket = SocketHead; socket; socket = socket->next)
994
         {
995
            if(packet[IP_PROTOCOL] == socket->headerRcv[IP_PROTOCOL] &&
996
               memcmp(packet+UDP_DEST_PORT, socket->headerRcv+UDP_DEST_PORT, 2) == 0)
997
            {
998 209 rhoads
               EthernetCreateResponse(socket->headerSend, packet, UDP_DATA);
999 155 rhoads
               break;
1000
            }
1001
         }
1002
      }
1003
 
1004
      if(socket)
1005
      {
1006
         if(IPVerbose)
1007
            printf("U");
1008
         FrameInsert(&socket->frameReadHead, &socket->frameReadTail, frameIn);
1009 225 rhoads
         OS_Job(socket->funcPtr, socket, 0, 0);
1010 155 rhoads
         return 1;
1011
      }
1012
   }
1013
   return 0;
1014
}
1015
 
1016
 
1017 220 rhoads
#ifndef WIN32
1018 209 rhoads
static void IPMainThread(void *arg)
1019 155 rhoads
{
1020
   uint32 message[4];
1021
   int rc;
1022
   IPFrame *frame, *frameOut=NULL;
1023
   uint32 ticks, ticksLast;
1024 209 rhoads
   (void)arg;
1025 155 rhoads
 
1026
   ticksLast = OS_ThreadTime();
1027
   memset(message, 0, sizeof(message));
1028
 
1029
   for(;;)
1030
   {
1031
      Led(0);
1032
      rc = OS_MQueueGet(IPMQueue, message, 10);
1033
      if(rc == 0)
1034
      {
1035
         frame = (IPFrame*)message[1];
1036
         if(message[0] == 0)       //frame received
1037
         {
1038
            Led(1);
1039
            frame->length = (uint16)message[2];
1040 247 rhoads
            rc = IPProcessEthernetPacket(frame, frame->length);
1041 155 rhoads
            if(rc == 0)
1042
               FrameFree(frame);
1043
         }
1044
         else if(message[0] == 1)  //frame sent
1045
         {
1046
            Led(2);
1047
            assert(frame == frameOut);
1048
            IPFrameReschedule(frame);
1049
            frameOut = NULL;
1050
         }
1051
         else if(message[0] == 2)  //frame ready to send
1052
         {
1053
         }
1054
      }
1055
 
1056
      if(frameOut == NULL)
1057
      {
1058 157 rhoads
         OS_MutexPend(IPMutex);
1059 155 rhoads
         frameOut = FrameSendTail;
1060
         if(frameOut)
1061
            FrameRemove(&FrameSendHead, &FrameSendTail, frameOut);
1062 157 rhoads
         OS_MutexPost(IPMutex);
1063 155 rhoads
         if(frameOut)
1064
         {
1065
            Led(4);
1066
            UartPacketSend(frameOut->packet, frameOut->length);
1067
         }
1068
      }
1069
 
1070
      ticks = OS_ThreadTime();
1071
      if(ticks - ticksLast > 100)
1072
      {
1073
         IPTick();
1074
         ticksLast = ticks;
1075
      }
1076
   }
1077
}
1078 220 rhoads
#endif
1079 155 rhoads
 
1080
 
1081 157 rhoads
uint8 *MyPacketGet(void)
1082 155 rhoads
{
1083 160 rhoads
   return (uint8*)IPFrameGet(FRAME_COUNT_RCV);
1084 155 rhoads
}
1085
 
1086
 
1087
//Set FrameSendFunction only if single threaded
1088 296 rhoads
void IPInit(IPFuncPtr frameSendFunction, uint8 macAddress[6], char name[6])
1089 155 rhoads
{
1090
   int i;
1091
   IPFrame *frame;
1092
 
1093 296 rhoads
   if(macAddress)
1094
      memcpy(ethernetAddressPlasma, macAddress, 6);
1095
   if(name)
1096
      memcpy(dhcpOptions+18, name, 6);
1097 209 rhoads
   FrameSendFunc = frameSendFunction;
1098 157 rhoads
   IPMutex = OS_MutexCreate("IPSem");
1099 155 rhoads
   IPMQueue = OS_MQueueCreate("IPMQ", FRAME_COUNT*2, 32);
1100
   for(i = 0; i < FRAME_COUNT; ++i)
1101
   {
1102
      frame = (IPFrame*)malloc(sizeof(IPFrame));
1103
      memset(frame, 0, sizeof(IPFrame));
1104
      frame->next = FrameFreeHead;
1105
      frame->prev = NULL;
1106
      FrameFreeHead = frame;
1107
   }
1108 296 rhoads
   FrameFreeCount = FRAME_COUNT;
1109 302 rhoads
#ifndef WIN32
1110 155 rhoads
   UartPacketConfig(MyPacketGet, PACKET_SIZE, IPMQueue);
1111 209 rhoads
   if(frameSendFunction == NULL)
1112 157 rhoads
      IPThread = OS_ThreadCreate("TCP/IP", IPMainThread, NULL, 240, 6000);
1113 302 rhoads
#endif
1114 155 rhoads
   IPDhcp(NULL, 360, 1);        //Send DHCP request
1115
}
1116
 
1117
 
1118 209 rhoads
//To open a socket for listen set ipAddress to 0
1119
IPSocket *IPOpen(IPMode_e mode, uint32 ipAddress, uint32 port, IPFuncPtr funcPtr)
1120 155 rhoads
{
1121
   IPSocket *socket;
1122 160 rhoads
   uint8 *ptrSend, *ptrRcv;
1123
   IPFrame *frame;
1124
   static int portSource=0x1007;
1125 155 rhoads
 
1126
   socket = (IPSocket*)malloc(sizeof(IPSocket));
1127
   if(socket == NULL)
1128
      return socket;
1129
   memset(socket, 0, sizeof(IPSocket));
1130
   socket->prev = NULL;
1131
   socket->state = IP_LISTEN;
1132
   socket->timeout = 0;
1133 231 rhoads
   socket->timeoutReset = SOCKET_TIMEOUT;
1134 155 rhoads
   socket->frameReadHead = NULL;
1135
   socket->frameReadTail = NULL;
1136
   socket->readOffset = 0;
1137
   socket->funcPtr = funcPtr;
1138
   socket->userData = 0;
1139
   socket->userFunc = NULL;
1140
   socket->userPtr = NULL;
1141 160 rhoads
   ptrSend = socket->headerSend;
1142
   ptrRcv = socket->headerRcv;
1143 155 rhoads
 
1144 209 rhoads
   if(ipAddress == 0)
1145 155 rhoads
   {
1146
      //Setup listing port
1147 209 rhoads
      socket->headerRcv[TCP_DEST_PORT] = (uint8)(port >> 8);
1148
      socket->headerRcv[TCP_DEST_PORT+1] = (uint8)port;
1149 155 rhoads
   }
1150
   else
1151
   {
1152 160 rhoads
      //Setup sending packet
1153
      memset(ptrSend, 0, UDP_LENGTH);
1154
      memset(ptrRcv, 0, UDP_LENGTH);
1155 155 rhoads
 
1156 160 rhoads
      //Setup Ethernet
1157 209 rhoads
      if(ipAddress != IPAddressSelf())
1158
         memcpy(ptrSend+ETHERNET_DEST, ethernetAddressGateway, 6);
1159
      else
1160
         memcpy(ptrSend+ETHERNET_DEST, ethernetAddressPlasma, 6);
1161 160 rhoads
      memcpy(ptrSend+ETHERNET_SOURCE, ethernetAddressPlasma, 6);
1162
      ptrSend[ETHERNET_FRAME_TYPE] = 0x08;
1163
 
1164
      //Setup IP
1165
      ptrSend[IP_VERSION_LENGTH] = 0x45;
1166
      ptrSend[IP_TIME_TO_LIVE] = 0x80;
1167
 
1168
      //Setup IP addresses
1169
      memcpy(ptrSend+IP_SOURCE, ipAddressPlasma, 4);
1170 209 rhoads
      ptrSend[IP_DEST] = (uint8)(ipAddress >> 24);
1171
      ptrSend[IP_DEST+1] = (uint8)(ipAddress >> 16);
1172
      ptrSend[IP_DEST+2] = (uint8)(ipAddress >> 8);
1173
      ptrSend[IP_DEST+3] = (uint8)ipAddress;
1174
      ptrRcv[IP_SOURCE] = (uint8)(ipAddress >> 24);
1175
      ptrRcv[IP_SOURCE+1] = (uint8)(ipAddress >> 16);
1176
      ptrRcv[IP_SOURCE+2] = (uint8)(ipAddress >> 8);
1177
      ptrRcv[IP_SOURCE+3] = (uint8)ipAddress;
1178 160 rhoads
      memcpy(ptrRcv+IP_DEST, ipAddressPlasma, 4);
1179
 
1180
      //Setup ports
1181
      ptrSend[TCP_SOURCE_PORT] = (uint8)(portSource >> 8);
1182
      ptrSend[TCP_SOURCE_PORT+1] = (uint8)portSource;
1183 209 rhoads
      ptrSend[TCP_DEST_PORT] = (uint8)(port >> 8);
1184
      ptrSend[TCP_DEST_PORT+1] = (uint8)port;
1185
      ptrRcv[TCP_SOURCE_PORT] = (uint8)(port >> 8);
1186
      ptrRcv[TCP_SOURCE_PORT+1] = (uint8)port;
1187 160 rhoads
      ptrRcv[TCP_DEST_PORT] = (uint8)(portSource >> 8);
1188
      ptrRcv[TCP_DEST_PORT+1] = (uint8)portSource;
1189 155 rhoads
      ++portSource;
1190
   }
1191
 
1192 209 rhoads
   if(mode == IP_MODE_TCP)
1193 155 rhoads
   {
1194 209 rhoads
      if(ipAddress)
1195 160 rhoads
         socket->state = IP_TCP;
1196
      else
1197
         socket->state = IP_LISTEN;
1198
      ptrSend[IP_PROTOCOL] = 0x06;  //TCP
1199
      ptrRcv[IP_PROTOCOL] = 0x06;
1200 155 rhoads
   }
1201 209 rhoads
   else if(mode == IP_MODE_UDP)
1202 155 rhoads
   {
1203
      socket->state = IP_UDP;
1204 160 rhoads
      ptrSend[IP_PROTOCOL] = 0x11;  //UDP
1205
      ptrRcv[IP_PROTOCOL] = 0x11;
1206 155 rhoads
   }
1207 209 rhoads
   else if(mode == IP_MODE_PING)
1208
   {
1209
      socket->state = IP_PING;
1210
      ptrSend[IP_PROTOCOL] = 0x01;  //PING
1211
      memset(ptrSend+PING_TYPE, 0, 8);
1212
      ptrSend[PING_TYPE] = 8;       //SEND
1213
   }
1214 155 rhoads
 
1215 160 rhoads
   //Add socket to linked list
1216 157 rhoads
   OS_MutexPend(IPMutex);
1217 155 rhoads
   socket->next = SocketHead;
1218 160 rhoads
   socket->prev = NULL;
1219
   if(SocketHead)
1220
      SocketHead->prev = socket;
1221 155 rhoads
   SocketHead = socket;
1222 157 rhoads
   OS_MutexPost(IPMutex);
1223 160 rhoads
 
1224 209 rhoads
   if(mode == IP_MODE_TCP && ipAddress)
1225 160 rhoads
   {
1226
      //Send TCP SYN
1227 206 rhoads
      socket->seq = 0x01234567;
1228 160 rhoads
      frame = IPFrameGet(0);
1229
      if(frame)
1230
      {
1231
         frame->packet[TCP_FLAGS] = TCP_FLAGS_SYN;
1232
         frame->packet[TCP_DATA] = 2;    //maximum segment size = 536
1233
         frame->packet[TCP_DATA+1] = 4;
1234
         frame->packet[TCP_DATA+2] = 2;
1235
         frame->packet[TCP_DATA+3] = 24;
1236
         TCPSendPacket(socket, frame, TCP_DATA+4);
1237
         ++socket->seq;
1238
      }
1239
   }
1240 155 rhoads
   return socket;
1241
}
1242
 
1243
 
1244 209 rhoads
void IPWriteFlush(IPSocket *socket)
1245 155 rhoads
{
1246
   uint8 *packetOut;
1247 209 rhoads
   if(socket->frameSend && socket->state != IP_UDP &&
1248
      socket->state != IP_PING)
1249 155 rhoads
   {
1250 209 rhoads
      packetOut = socket->frameSend->packet;
1251 220 rhoads
      packetOut[TCP_FLAGS] = TCP_FLAGS_ACK | TCP_FLAGS_PSH;
1252 209 rhoads
      TCPSendPacket(socket, socket->frameSend, TCP_DATA + socket->sendOffset);
1253
      socket->seq += socket->sendOffset;
1254
      socket->frameSend = NULL;
1255
      socket->sendOffset = 0;
1256 155 rhoads
   }
1257
}
1258
 
1259
 
1260 209 rhoads
uint32 IPWrite(IPSocket *socket, const uint8 *buf, uint32 length)
1261 155 rhoads
{
1262
   IPFrame *frameOut;
1263
   uint8 *packetOut;
1264 206 rhoads
   uint32 bytes, count=0, tries=0;
1265 155 rhoads
   int offset;
1266 165 rhoads
   OS_Thread_t *self;
1267 155 rhoads
 
1268 231 rhoads
   if(socket->timeout)
1269
      socket->timeout = socket->timeoutReset;
1270
 
1271 155 rhoads
   //printf("IPWrite(0x%x, %d)", Socket, Length);
1272 165 rhoads
   self = OS_ThreadSelf();
1273 209 rhoads
   while(length)
1274 155 rhoads
   {
1275 206 rhoads
      //Rate limit output
1276 209 rhoads
      if(socket->seq - socket->seqReceived >= 5120)
1277 206 rhoads
      {
1278 302 rhoads
         //printf("l(%d,%d,%d) ", socket->seq - socket->seqReceived, socket->seq, socket->seqReceived);
1279 206 rhoads
         if(self == IPThread || ++tries > 200)
1280
            break;
1281
         else
1282
         {
1283
            OS_ThreadSleep(1);
1284
            continue;
1285
         }
1286
      }
1287 165 rhoads
      tries = 0;
1288 209 rhoads
      while(socket->frameSend == NULL)
1289 155 rhoads
      {
1290 209 rhoads
         socket->frameSend = IPFrameGet(FRAME_COUNT_SEND);
1291
         socket->sendOffset = 0;
1292
         if(socket->frameSend == NULL)
1293 165 rhoads
         {
1294 302 rhoads
            //printf("L");
1295 165 rhoads
            if(self == IPThread || ++tries > 200)
1296
               break;
1297
            else
1298
               OS_ThreadSleep(1);
1299
         }
1300 155 rhoads
      }
1301 209 rhoads
      frameOut = socket->frameSend;
1302
      offset = socket->sendOffset;
1303 155 rhoads
      if(frameOut == NULL)
1304
         break;
1305
      packetOut = frameOut->packet;
1306
 
1307 209 rhoads
      if(socket->state == IP_PING)
1308 155 rhoads
      {
1309 209 rhoads
         bytes = length;
1310
         memcpy(packetOut, socket->headerSend, PING_DATA);
1311
         memcpy(packetOut+PING_DATA, buf, bytes);
1312
         IPSendPacket(socket, socket->frameSend, PING_DATA + bytes);
1313
         socket->frameSend = NULL;
1314
      }
1315
      else if(socket->state != IP_UDP)
1316
      {
1317
         bytes = 512 - offset;
1318
         if(bytes > length)
1319
            bytes = length;
1320
         socket->sendOffset += bytes;
1321
         memcpy(packetOut+TCP_DATA+offset, buf, bytes);
1322
         if(socket->sendOffset >= 512)
1323
            IPWriteFlush(socket);
1324 165 rhoads
         //if(Socket->seq - Socket->seqReceived > Socket->seqWindow)
1325
         //{
1326
         //   printf("W");
1327
         //   OS_ThreadSleep(10);
1328
         //}
1329 155 rhoads
      }
1330
      else  //UDP
1331
      {
1332 209 rhoads
         bytes = length;
1333
         memcpy(packetOut+UDP_DATA+offset, buf, bytes);
1334
         memcpy(packetOut, socket->headerSend, UDP_LENGTH);
1335
         IPSendPacket(socket, socket->frameSend, UDP_DATA + bytes);
1336
         socket->frameSend = NULL;
1337 155 rhoads
      }
1338
      count += bytes;
1339 209 rhoads
      buf += bytes;
1340
      length -= bytes;
1341 155 rhoads
   }
1342
   return count;
1343
}
1344
 
1345
 
1346 209 rhoads
uint32 IPRead(IPSocket *socket, uint8 *buf, uint32 length)
1347 155 rhoads
{
1348
   IPFrame *frame, *frame2;
1349
   int count=0, bytes, offset;
1350
 
1351 225 rhoads
   if(socket->state == IP_UDP)
1352
      offset = UDP_DATA;
1353
   else
1354 155 rhoads
      offset = TCP_DATA;
1355
 
1356 157 rhoads
   OS_MutexPend(IPMutex);
1357 209 rhoads
   for(frame = socket->frameReadTail; length && frame; )
1358 155 rhoads
   {
1359 209 rhoads
      bytes = frame->length - offset - socket->readOffset;
1360
      if(bytes > (int)length)
1361
         bytes = length;
1362
      memcpy(buf, frame->packet + offset + socket->readOffset, bytes);
1363
      buf += bytes;
1364
      socket->readOffset += bytes;
1365
      length -= bytes;
1366 155 rhoads
      count += bytes;
1367
 
1368
      //Check if done with packet
1369
      frame2 = frame;
1370
      frame = frame->prev;
1371 209 rhoads
      if(socket->readOffset == frame2->length - offset)
1372 155 rhoads
      {
1373
         //Remove packet from socket linked list
1374 209 rhoads
         socket->readOffset = 0;
1375
         FrameRemove(&socket->frameReadHead, &socket->frameReadTail, frame2);
1376 155 rhoads
         FrameFree(frame2);
1377
      }
1378
   }
1379 157 rhoads
   OS_MutexPost(IPMutex);
1380 155 rhoads
   return count;
1381
}
1382
 
1383
 
1384 209 rhoads
static void IPClose2(IPSocket *socket)
1385 155 rhoads
{
1386
   IPFrame *frame, *framePrev;
1387
 
1388 157 rhoads
   OS_MutexPend(IPMutex);
1389 155 rhoads
 
1390 157 rhoads
   //Mark packets as don't retransmit
1391
   for(frame = FrameSendHead; frame; frame = frame->next)
1392 155 rhoads
   {
1393 209 rhoads
      if(frame->socket == socket)
1394 157 rhoads
         frame->socket = NULL;
1395 155 rhoads
   }
1396
 
1397
   //Remove packets from retransmision list
1398
   for(frame = FrameResendHead; frame; )
1399
   {
1400
      framePrev = frame;
1401
      frame = frame->next;
1402 209 rhoads
      if(framePrev->socket == socket)
1403 155 rhoads
      {
1404
         FrameRemove(&FrameResendHead, &FrameResendTail, framePrev);
1405
         FrameFree(framePrev);
1406
      }
1407
   }
1408
 
1409
   //Remove packets from socket read linked list
1410 209 rhoads
   for(frame = socket->frameReadHead; frame; )
1411 155 rhoads
   {
1412
      framePrev = frame;
1413
      frame = frame->next;
1414 209 rhoads
      FrameRemove(&socket->frameReadHead, &socket->frameReadTail, framePrev);
1415 155 rhoads
      FrameFree(framePrev);
1416
   }
1417
 
1418
   //Remove socket
1419 225 rhoads
   if(socket->state == IP_CLOSED)
1420
   {
1421
      if(socket->prev == NULL)
1422
         SocketHead = socket->next;
1423
      else
1424
         socket->prev->next = socket->next;
1425
      if(socket->next)
1426
         socket->next->prev = socket->prev;
1427
      free(socket);
1428
   }
1429 155 rhoads
   else
1430 225 rhoads
   {
1431
      //Give application 10 seconds to stop using socket
1432
      socket->state = IP_CLOSED;
1433
      socket->timeout = 10;
1434
   }
1435 157 rhoads
   OS_MutexPost(IPMutex);
1436 155 rhoads
}
1437
 
1438
 
1439 209 rhoads
void IPClose(IPSocket *socket)
1440 155 rhoads
{
1441
   IPFrame *frameOut;
1442
 
1443 209 rhoads
   IPWriteFlush(socket);
1444
   if(socket->state <= IP_UDP)
1445 157 rhoads
   {
1446 209 rhoads
      IPClose2(socket);
1447 157 rhoads
      return;
1448
   }
1449
   frameOut = IPFrameGet(0);
1450 231 rhoads
   if(frameOut == NULL)
1451 155 rhoads
      return;
1452
   frameOut->packet[TCP_FLAGS] = TCP_FLAGS_FIN | TCP_FLAGS_ACK;
1453 209 rhoads
   TCPSendPacket(socket, frameOut, TCP_DATA);
1454
   ++socket->seq;
1455
   if(socket->state == IP_FIN_CLIENT)
1456
      IPClose2(socket);
1457 157 rhoads
   else
1458 209 rhoads
      socket->state = IP_FIN_SERVER;
1459 155 rhoads
}
1460
 
1461
 
1462 209 rhoads
void IPPrintf(IPSocket *socket, char *message)
1463
{
1464
   IPWrite(socket, (uint8*)message, (int)strlen(message));
1465
   IPWriteFlush(socket);
1466
}
1467 155 rhoads
 
1468
 
1469
void IPTick(void)
1470
{
1471
   IPFrame *frame, *frame2;
1472
   IPSocket *socket, *socket2;
1473 296 rhoads
   unsigned long ticks;
1474
   static unsigned long ticksPrev=0, ticksPrev2=0;
1475 155 rhoads
 
1476 296 rhoads
   ticks = OS_ThreadTime();
1477
   if(ticks - ticksPrev >= 95)
1478 157 rhoads
   {
1479 296 rhoads
      if(IPVerbose && (Seconds % 60) == 0)
1480
      {
1481
         if(FrameFreeCount >= FRAME_COUNT-1)
1482
            printf("T");
1483
         else
1484
            printf("T(%d)", FrameFreeCount);
1485
      }
1486
      ++Seconds;
1487
      if(--DhcpRetrySeconds <= 0)
1488
         IPDhcp(NULL, 400, 1);   //DHCP request
1489 157 rhoads
   }
1490 155 rhoads
 
1491 157 rhoads
   OS_MutexPend(IPMutex);
1492 155 rhoads
 
1493
   //Retransmit timeout packets
1494
   for(frame = FrameResendHead; frame; )
1495
   {
1496
      frame2 = frame;
1497
      frame = frame->next;
1498 302 rhoads
      frame2->timeout = (short)(frame2->timeout - (ticks - ticksPrev2));
1499 296 rhoads
      if(--frame2->timeout <= 0)
1500 155 rhoads
      {
1501
         if(IPVerbose)
1502
            printf("r");
1503
         FrameRemove(&FrameResendHead, &FrameResendTail, frame2);
1504
         IPSendFrame(frame2);
1505
      }
1506
   }
1507
 
1508 296 rhoads
   if(ticks - ticksPrev >= 95)
1509 155 rhoads
   {
1510 296 rhoads
      //Close timed out sockets
1511
      for(socket = SocketHead; socket; )
1512 155 rhoads
      {
1513 296 rhoads
         socket2 = socket;
1514
         socket = socket->next;
1515
         if(socket2->timeout && --socket2->timeout == 0)
1516
         {
1517
            socket2->timeout = 10;
1518
            if(IPVerbose && socket2->state != IP_CLOSED &&
1519
                            socket2->state != IP_FIN_SERVER)
1520
               printf("t(%d,%d)", socket2->state, FrameFreeCount);
1521
            if(socket2->state == IP_TCP)
1522
               IPClose(socket2);
1523
            else if(socket2->state == IP_FIN_CLIENT)
1524
               IPClose(socket2);
1525
            else
1526
               IPClose2(socket2);
1527
         }
1528 155 rhoads
      }
1529 296 rhoads
      ticksPrev = ticks;
1530 155 rhoads
   }
1531 157 rhoads
   OS_MutexPost(IPMutex);
1532 296 rhoads
   ticksPrev2 = ticks;
1533 155 rhoads
}
1534
 
1535
 
1536
static void DnsCallback(IPSocket *socket)
1537
{
1538
   uint8 buf[200], *ptr;
1539
   uint32 ipAddress;
1540 209 rhoads
   int bytes;
1541 155 rhoads
 
1542
   memset(buf, 0, sizeof(buf));
1543 209 rhoads
   bytes = IPRead(socket, buf, sizeof(buf));
1544 155 rhoads
   if(buf[DNS_NUM_ANSWERS_RR+1])
1545
   {
1546 209 rhoads
      for(ptr = buf + DNS_QUESTIONS; ptr + 14 <= buf + bytes; ++ptr)
1547 155 rhoads
      {
1548 211 rhoads
         if(ptr[0] == 0 && ptr[1] == 1 && ptr[2] == 0 && ptr[3] == 1 &&
1549
            ptr[8] == 0 && ptr[9] == 4)
1550 155 rhoads
         {
1551 211 rhoads
            ipAddress = (ptr[10] << 24) | (ptr[11] << 16) | (ptr[12] << 8) | ptr[13];
1552
            printf("ipAddress = %d.%d.%d.%d\n", ptr[10], ptr[11], ptr[12], ptr[13]);
1553 155 rhoads
            socket->userData = ipAddress;
1554
            if(socket->userFunc)
1555
            {
1556 209 rhoads
               socket->userFunc(socket, ipAddress, socket->userPtr);
1557 155 rhoads
            }
1558
            break;
1559
         }
1560
      }
1561
   }
1562 220 rhoads
   IPClose(socket);
1563 155 rhoads
}
1564
 
1565
 
1566 220 rhoads
void IPResolve(char *name, IPFuncPtr resolvedFunc, void *arg)
1567 155 rhoads
{
1568
   uint8 buf[200], *ptr;
1569
   int length, i;
1570
   IPSocket *socket;
1571
 
1572
   socket = IPOpen(IP_MODE_UDP, ipAddressDns, DNS_PORT, DnsCallback);
1573
   memset(buf, 0, sizeof(buf));
1574
   buf[DNS_ID+1] = 1;
1575
   buf[DNS_FLAGS] = 1;
1576
   buf[DNS_NUM_QUESTIONS+1] = 1;
1577
 
1578
   //Setup name
1579
   ptr = buf + DNS_QUESTIONS;
1580 209 rhoads
   strncpy((char*)ptr+1, name, 100);
1581 155 rhoads
   ptr[0] = 1;
1582
   while(ptr[0])
1583
   {
1584
      for(i = 0; i < 100; ++i)
1585
      {
1586
         if(ptr[i+1] == '.' || ptr[i+1] == 0)
1587
         {
1588
            ptr[0] = (uint8)i;
1589
            ptr += i+1;
1590
            break;
1591
         }
1592
      }
1593
   }
1594
   ++ptr;
1595
   ptr[1] = DNS_QUERY_TYPE_IP;
1596
   ptr[3] = DNS_QUERY_CLASS;
1597
   length = (int)(ptr - buf) + 4;
1598
   if(length < 60)
1599
      length = 60;
1600
 
1601
   socket->userFunc = (IPFuncPtr)resolvedFunc;
1602 209 rhoads
   socket->userPtr = arg;
1603 155 rhoads
   socket->userData = 0;
1604
   IPWrite(socket, buf, length);
1605
}
1606
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.