Subversion Repositories shark

Rev

Rev 3 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 pj 1
/*
2
 * Project: S.Ha.R.K.
3
 *
4
 * Coordinators:
5
 *   Giorgio Buttazzo    <giorgio@sssup.it>
6
 *   Paolo Gai           <pj@gandalf.sssup.it>
7
 *
8
 * Authors     :
9
 *   Paolo Gai           <pj@gandalf.sssup.it>
10
 *   Massimiliano Giorgi <massy@gandalf.sssup.it>
11
 *   Luca Abeni          <luca@gandalf.sssup.it>
12
 *   (see the web pages for full authors list)
13
 *
14
 * ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
15
 *
16
 * http://www.sssup.it
17
 * http://retis.sssup.it
18
 * http://shark.sssup.it
19
 */
20
 
21
/**
22
 ------------
217 giacomo 23
 CVS :        $Id: udpip.c,v 1.2 2003-09-02 16:12:40 giacomo Exp $
2 pj 24
 
25
 File:        $File$
217 giacomo 26
 Revision:    $Revision: 1.2 $
27
 Last update: $Date: 2003-09-02 16:12:40 $
2 pj 28
 ------------
29
**/
30
 
31
/*
32
 * Copyright (C) 2000 Luca Abeni and Giuseppe Lipari
33
 *
34
 * This program is free software; you can redistribute it and/or modify
35
 * it under the terms of the GNU General Public License as published by
36
 * the Free Software Foundation; either version 2 of the License, or
37
 * (at your option) any later version.
38
 *
39
 * This program is distributed in the hope that it will be useful,
40
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
41
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
42
 * GNU General Public License for more details.
43
 *
44
 * You should have received a copy of the GNU General Public License
45
 * along with this program; if not, write to the Free Software
46
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
47
 *
48
 */
49
 
50
/* Author:      Giuseppe Lipari & Luca Abeni                    */
51
/* Date:        1/12/97                                         */
52
 
53
/* File:        UDPIPDrv.C                                      */
54
/* Revision:    2.0                                             */
55
 
56
/*
57
   UDP and IP layers. IP doesn't support fragmented packets (fragmentation
58
   isn't Real-Time!!!). UDP allows to fill some entries of the ARP table
59
   at the moment of the creation of a socket (see udp_bind).
60
*/
61
 
62
#include <kernel/kern.h>
63
#include <semaphore.h>
64
 
65
#include "eth_priv.h"
66
#include "netbuff.h"
67
#include <drivers/udpip.h>
68
#include "arp.h"
69
 
70
/*
71
   UDP-buffers number and dimension (UDP-buffers are provided by NetBuff
72
   module
73
*/
74
#define UDP_RX_BUFFERS  4
75
#define UDP_TX_BUFFERS  4
76
#define UDP_MAX_LEN     1000
77
#define UDP_MAX_HANDLES 4
78
 
79
/* Only 4 debug */
80
extern int netlev;
81
 
82
int ipIsInstalled = FALSE;
83
extern struct ip_addr myIpAddr;
84
struct ip_table ipTable[IP_MAX_ENTRIES];
85
extern ARP_TABLE arpTable[ARP_MAX_ENTRIES];
86
 
87
int udpIsInstalled = FALSE;
88
struct netbuff udp_txbuff;
89
struct netbuff udp_rxbuff;
90
struct udp_table udpTable[UDP_MAX_HANDLES];
91
 
92
 
93
IP_ADDR *ip_getAddr()
94
{
95
    return &myIpAddr;
96
}
97
 
98
/* TRUE if the IP addresses ip1 and ip2 are equal, FALSE otherwise */
99
int ip_compAddr(IP_ADDR ip1, IP_ADDR ip2)
100
{
101
    int i;
102
 
103
    for (i=0; i < 4; i++)
104
        if (ip1.ad[i] != ip2.ad[i]) return FALSE;
105
    return TRUE;
106
}
107
 
108
/* traslate an IP address from text string to 4 bytes */
109
int ip_str2addr(char *a, IP_ADDR *ip)
110
{
111
    int ad[6];
112
    int i,j;
113
    char c;
114
 
115
    i = 0;
116
    for(j = 0; j < 4; j++) {
117
        ad[j] = 0;
118
        while((a[i] != '.') && (a[i] != 0)) {
119
            c = a[i++];
120
            if (c <= '9') c = c - '0';
121
            else c = c - 'A' + 10;
122
            ad[j] = ad[j] * 10 + c;
123
        }
124
        i++;
125
    }
126
 
127
    for (i=0; i<4; i++) ip->ad[i] = ad[i];
128
    return 1;
129
}
130
 
131
/* give the body of an IP packet */
132
void *ip_getFDB(void *pkt)
133
{
134
    return((void *)(((BYTE *)eth_getFDB(pkt)) + sizeof(IP_HEADER)));
135
}
136
 
137
/* received IP packet CallBack */
138
void ip_server_recv(void *pkt)
139
{
140
    IP_HEADER *iphd;
141
    WORD *ptcheck;
142
    WORD checksum,oldChk;
143
    int hlen,i;
144
    int done;
145
    char dummystr[50];
146
    BYTE flag;
147
 
148
    UDP_HEADER *udphd;
149
    struct pseudo_hd ph;
150
    WORD sum, old;
151
    WORD *p;
152
    UDP_MSG usermsg;
153
    void *b, *s;
154
 
155
/* debug...*/
156
netlev = 2;
157
 
158
    sprintf(dummystr, "Packet arrived!\n");
159
    iphd = (IP_HEADER *)eth_getFDB(pkt);
160
/* compute the checksum */
161
    ptcheck = (WORD *)iphd;
162
#ifdef __IP_DBG__
163
ip_print_header(iphd);
164
#endif
165
    hlen = getHlen(iphd->vers_hlen) * 2;
166
    checksum = oldChk = *ptcheck;
167
    ptcheck++;
168
    for (i=1; i<hlen; i++) {
169
        checksum += *ptcheck;
170
        if (checksum < oldChk) checksum ++;
171
        oldChk = checksum;
172
        ptcheck++;
173
    }
174
    if (checksum != 0xffff) {
175
/* wrong ChkSum */
176
#ifdef __IP_DBG__
177
sprintf(msg, "Wrong checksum! %x\n",checksum);
178
win_puts(&wip,msg);
179
#endif
180
    } else if (!ip_compAddr(iphd->dest,myIpAddr)) {
181
#ifdef __IP_DBG__
182
win_puts(&wip,"Packet not addressed to this host!\n");
183
#endif
184
    } else if (getFlags(ntohs(iphd->flags_frOffset)) & 0x01) {
185
#ifdef __IP_DBG__
186
/* fragment? */
187
win_puts(&wip,"Gotta a fragment!\n");
188
#endif
189
    } else if (getFrOffset(ntohs(iphd->flags_frOffset)) != 0) {
190
#ifdef __IP_DBG__
191
win_puts(&wip,"Gotta a fragment again!\n");
192
#endif
193
    } else {
194
        /* OK: the packet is good... */
195
        if (iphd->protocol != IP_UDP_TYPE) {
196
            /* It isn't an UDP packet */
197
            done = FALSE;
198
            i = 0;
199
            while ((i < IP_MAX_ENTRIES) && !done) {
200
                if (ipTable[i].protocol == iphd->protocol) done = TRUE;
201
                else i++;
202
            }
203
            if (!done) {
204
#ifdef __IP_DBG__
205
/* Unknown transport protocol */
206
win_puts(&wip,"Wrong protocol\n");
207
#endif
208
            } else {
209
                /* Call the correct transport protocol CallBack */
210
                ipTable[i].rfun((void *)((BYTE *)iphd + 4*getHlen(iphd->vers_hlen)));
211
            }
212
        } else {
213
            /* UDP packet */
214
netlev = 4;
215
            udphd = (UDP_HEADER *)(void *)((BYTE *)iphd + 4*getHlen(iphd->vers_hlen));
216
            /* compute the UDP checksum */
217
            for (i = 0; i < 4; i++) {
218
                ph.source.ad[i]  = iphd->source.ad[i];
219
                ph.dest.ad[i]  = iphd->dest.ad[i];
220
            }
221
            ph.zero = 0;
222
            ph.protocoll = IP_UDP_TYPE;
223
            ph.len = udphd->mlen;
224
            sum = 0;
225
            old = 0;
226
            p = (WORD *)&ph;
227
            for (i = 0; i < (sizeof(ph) >> 1); i++) {
228
                sum += p[i];
229
                if (sum < old) sum ++;
230
                old = sum;
231
            }
232
#ifdef __UDP_DBG__
233
sprintf(str,"half sum: %x\n",sum);
234
win_puts(&dbg,str);
235
#endif
236
            p = (WORD *)udphd;
237
            ((BYTE *)udphd)[ntohs(udphd->mlen)] = 0;
238
            for (i = 0; i < ((ntohs(udphd->mlen) + 1) >> 1); i++) {
239
                sum += p[i];
240
                if (sum < old) sum ++;
241
                old = sum;
242
            }
243
#ifdef __UDP_DBG__
244
win_puts(&dbg,"UDP packet received!!!\n");
245
sprintf(str,"s_port: %x\n",udphd->s_port);
246
win_puts(&dbg,str);
247
sprintf(str,"d_port: %x\n",udphd->d_port);
248
win_puts(&dbg,str);
249
sprintf(str,"m_len: %x %d\n",udphd->mlen, ntohs(udphd->mlen));
250
win_puts(&dbg,str);
251
sprintf(str,"checksum: %x\n",udphd->checksum);
252
win_puts(&dbg,str);
253
sprintf(str,"mysum: %x \n", sum);
254
win_puts(&dbg,str);
255
#endif
256
            if(sum != 0xFFFF) {
257
                /* Wrong UDP ChkSum */
258
                cprintf("Error %x!!!!\n",sum);
259
                kern_raise(XUDP_BADCHK_EXC,exec_shadow);
260
            } else {
261
                done = FALSE;
262
                i = 0;
263
                /* searching for the destination socket...*/
264
                while((i < UDP_MAX_HANDLES) && !done) {
265
                    if ((udpTable[i].valid == TRUE) &&
266
                        (udpTable[i].port == ntohs(udphd->d_port)))
267
                            done = TRUE;
268
                    else i++;
269
                }
270
                if (done) {
271
                /*...found! */
272
                s = (void *)(((BYTE *)udphd) + sizeof(UDP_HEADER));
273
                    if (udpTable[i].notify == TRUE) {
274
                        /* notify function associated to the socket: call it */
275
                        udpTable[i].notify_fun(ntohs(udphd->mlen) - sizeof(UDP_HEADER),
276
                                                s, udpTable[i].notify_par);
277
                    } else {
278
                        /* otherwise, send the packet to the correct port */
279
                        if((b = netbuff_get(&udp_rxbuff, NON_BLOCK)) != 0) {
280
                            memcpy(b,s,ntohs(udphd->mlen) - sizeof(UDP_HEADER) + 1);
281
                            setIpAddr(usermsg.addr.s_addr, iphd->source);
282
                            usermsg.addr.s_port = ntohs(udphd->s_port);
283
                            usermsg.mlen = ntohs(udphd->mlen) - sizeof(UDP_HEADER);
284
                            usermsg.buff = b;
285
                            flag = port_send(udpTable[i].hport,&usermsg,NON_BLOCK);
286
                            if (!flag) {
287
                                netbuff_release(&udp_rxbuff, b);
288
#ifdef __UDP_DBG__
289
win_puts(&dbg,"Port is filled up       ");
290
#endif
291
                            }
292
                        }
293
                    }
294
                } else {
295
#ifdef __UDP_DBG__
296
win_puts(&dbg,"Port not found       ");
297
#endif
298
                }
299
            }
300
        }
301
    }
302
}
303
 
304
/* Send an IP packet */
305
void ip_send(IP_ADDR dest, void *pkt, WORD len)
306
{
307
    static WORD ip_ident = 0;
308
    IP_HEADER *iphd;
309
    WORD check = 0, oldCheck = 0;
310
    int i, done;
311
    WORD *pt;
312
#ifdef __IP_DBG__
313
char msg[50];
314
#endif
315
 
316
    iphd = (IP_HEADER *)eth_getFDB(pkt);
317
    iphd->vers_hlen = (4 << 4) + 5;
318
    iphd->servType = 8;
319
    iphd->lenght = htons(len + sizeof(IP_HEADER));
320
    iphd->ident = htons(ip_ident++);
321
    iphd->flags_frOffset = 0;
322
    iphd->ttl = 10;
323
    iphd->protocol = IP_UDP_TYPE;
324
    iphd->headChecksum = 0;
325
    iphd->source = myIpAddr;
326
    iphd->dest = dest;
327
 
328
    /* Compute the checksum */
329
    pt = (WORD *)iphd;
330
    check = oldCheck = *pt;
331
    pt++;
332
    for (i = 1; i < 10; i++) {
333
        check += *pt;
334
        if (oldCheck > check) check++;
335
        oldCheck = check;
336
        pt++;
337
    }
338
    check = ~check;
339
    iphd->headChecksum = check;
340
#ifdef __IP_DBG__
341
sprintf(msg,"serv type : %d\n",iphd->servType);
342
win_puts(&wip,msg);
343
#endif
344
    /* Is the destination ethernet address in the ARP table? */
345
    i = 0; done = 0;
346
    while (i < ARP_MAX_ENTRIES && !done)
347
        if (arpTable[i].valid == TRUE) {
348
            if (ip_compAddr(dest,arpTable[i].ip)) {
349
                done = TRUE;
350
            } else i++;
351
        } else i++;
352
    if (done == FALSE) {
353
        /* No: call ARP to get the ethernet address */
354
        arp_send(pkt,dest,len + sizeof(IP_HEADER));
355
    }
356
    else {
357
        /* Yes: directly send the packet */
358
        eth_setHeader(pkt,arpTable[i].eth,ETH_IP_TYPE);
359
        eth_sendPkt(pkt,len + sizeof(IP_HEADER));
360
        netbuff_release(&udp_txbuff, (void *)pkt);
361
        arpTable[i].used++;
362
        if (arpTable[i].used > ARP_MAX_USED) arpTable[i].used = ARP_MAX_USED;
363
    }
364
}
365
 
366
/* let IP manage a new transport protocol */
367
int ip_setProtocol(BYTE proto, void (*recv)(void *m))
368
{
369
    BYTE done, i;
370
 
371
    i = 0; done = 0;
372
    while (i < IP_MAX_ENTRIES && !done)
373
        if (ipTable[i].rfun == NULL) done = TRUE;
374
        else i++;
375
    if (!done) return FALSE;
376
    else {
377
        ipTable[i].protocol = proto;
378
        ipTable[i].rfun = recv;
379
    }
380
    return TRUE;
381
}
382
 
383
//int ip_error(int code)
384
//{
385
//    cprintf("IP error\n");
386
/*    cprintf("Code [%d]\nCause : %s",code,ip_error_msg[code-IP_ERROR_BASE]);*/
387
//    return(0);
388
//}
389
 
390
/* Initialize the IP layer: it also call the ARP initialization function */
391
void ip_init(void *localAddr)
392
{
393
    int i;
394
 
395
    if (!ipIsInstalled) {
396
        arp_init(localAddr);
397
        //exc_set(IP_INIT_ERROR,ip_error);
398
        for (i=0; i < IP_MAX_ENTRIES; i++) ipTable[i].rfun = NULL;
399
 
400
        eth_setProtocol(ETH_IP_TYPE, ip_server_recv);
401
        ipIsInstalled = TRUE;
402
    } else cprintf("IP: already installed!!!\n");
403
}
404
 
405
/* Receive an UDP packet from a socket */
217 giacomo 406
int udp_recvfrom(int s, void *buff, UDP_ADDR *from)
2 pj 407
{
408
    UDP_MSG u;
409
 
410
    port_receive(udpTable[s].pport,&u,BLOCK);
411
    memcpy(buff,u.buff,u.mlen);
412
    netbuff_release(&udp_rxbuff, u.buff);
413
    *from = u.addr;
414
    return (u.mlen);
415
}
416
 
417
/* Associate a notify function to a socket */
418
int udp_notify(int s, int (*f)(int len, BYTE *buff, void *p), void *p)
419
{
420
    if (f == NULL) {
421
        udpTable[s].notify = FALSE;
422
        return 1;
423
    }
424
 
425
    if (udpTable[s].valid != TRUE) return -1;
426
    udpTable[s].notify = TRUE;
427
    udpTable[s].notify_fun = f;
428
    udpTable[s].notify_par = p;
429
    return 1;
430
}
431
 
432
/* Create a new socket binding it to a specified IP port */
433
int udp_bind(UDP_ADDR *local, IP_ADDR *bindlist)
434
{
435
    int i, j;
436
    BYTE done;
437
    char str[30];
438
 
439
    /* Search for a free entry in the socket table */
440
    i = 0; done = FALSE;
441
    while ((i < UDP_MAX_HANDLES) && !done) {
442
        kern_cli();
443
        if ((udpTable[i].valid == FALSE)){
444
            done = TRUE;
445
            udpTable[i].valid = 2;
446
        } else i++;
447
        kern_sti();
448
    }
449
    /* No free entries: bind fail! */
450
    if (!done) return -1;
451
    /* Create a receive port for the socket */
452
    udpTable[i].port = local->s_port;
453
    sprintf(str,"UDP%d",i);
454
    udpTable[i].hport = port_create(str,sizeof(UDP_MSG),4,STREAM,WRITE);
455
    udpTable[i].pport = port_connect(str,sizeof(UDP_MSG),STREAM,READ);
456
    udpTable[i].valid = TRUE;
457
   /*
458
   Request for the ethernet addresses associated to the IP addressed
459
   given in the bindlist
460
   */
461
    if (bindlist != NULL) {
462
        while (*(int*)bindlist != 0) {
463
            j = arp_req(*bindlist);
464
            arp_sendRequest(j);
217 giacomo 465
            bindlist ++;
2 pj 466
        }
467
    }
468
 
469
    return i;
470
}
471
 
472
/* Send an UDP packet */
217 giacomo 473
int udp_sendto(int s, void *buff, int nbytes, UDP_ADDR *to)
2 pj 474
{
475
    void *pkt;
476
    UDP_HEADER *udphd;
477
    char *msg;
478
#ifdef __UDP_DBG__
479
static int num_pack = 0;
480
char str[50];
481
#endif
482
    WORD sum, old;
483
    int i;
484
    struct pseudo_hd ph;
485
    WORD *p;
486
    IP_ADDR *source;
487
 
488
    pkt = netbuff_get(&udp_txbuff, BLOCK);
489
    udphd = (UDP_HEADER *)ip_getFDB(pkt);
490
    udphd->s_port = htons(udpTable[s].port);
491
    udphd->d_port = htons(to->s_port);
492
    udphd->mlen = htons((WORD)nbytes + sizeof(UDP_HEADER));
493
    msg = (char *)(((BYTE *)udphd) + sizeof(UDP_HEADER));
494
    if (nbytes > UDP_MAX_LEN) nbytes = UDP_MAX_LEN;
495
    memcpy(msg,buff,nbytes);
496
 
497
    source = ip_getAddr();
498
    /* Compute the CheckSum */
499
    udphd->checksum = 0;
500
    for (i = 0; i < 4; i++) {
501
        ph.source.ad[i]  = source->ad[i];
502
        ph.dest.ad[i]  = to->s_addr.ad[i];
503
    }
504
    ph.zero = 0;
505
    ph.protocoll = 17;
506
    ph.len = udphd->mlen;
507
    sum = 0; old = 0;
508
    p = (WORD *)&ph;
509
    for (i = 0; i < (sizeof(ph) >> 1); i++) {
510
        sum += p[i];
511
        if (sum < old) sum ++;
512
        old = sum;
513
    }
514
    p = (WORD *)udphd;
515
    ((BYTE *)udphd)[ntohs(udphd->mlen)] = 0;
516
    for (i = 0; i < ((ntohs(udphd->mlen) + 1) >> 1); i++) {
517
        sum += p[i];
518
        if (sum < old) sum++;
519
        old = sum;
520
    }
521
    udphd->checksum = ~sum;
522
 
523
    ip_send(to->s_addr, pkt, ((WORD)nbytes + sizeof(UDP_HEADER)));
524
#ifdef __UDP_DBG__
525
sprintf(str,"Packet sent %d;  ",num_pack++);
526
win_puts(&dbg,str);
527
#endif
528
 
529
    return nbytes;
530
}
531
 
532
void udp_init(void *dummy)
533
{
534
    int i;
535
 
536
    if (!udpIsInstalled) {
537
        netbuff_init(&udp_rxbuff, UDP_RX_BUFFERS, UDP_MAX_LEN);
538
        netbuff_init(&udp_txbuff, UDP_TX_BUFFERS, ETH_MAX_LEN);
539
 
540
        for (i = 0; i < UDP_MAX_HANDLES; i++) {
541
            udpTable[i].valid = FALSE;
542
            udpTable[i].notify = FALSE;
543
        }
544
        udpIsInstalled = TRUE;
545
    } else cprintf("UDP: Already installed!!!\n");
546
}