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

Subversion Repositories plasma

[/] [plasma/] [trunk/] [kernel/] [tcpip.c] - Blame information for rev 257

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

powered by: WebSVN 2.1.0

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