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

Subversion Repositories mlite

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

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

powered by: WebSVN 2.1.0

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