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

Subversion Repositories mlite

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

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

powered by: WebSVN 2.1.0

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