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

Subversion Repositories plasma

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

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

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

powered by: WebSVN 2.1.0

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