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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [net/] [tcpip/] [v2_0/] [src/] [sys/] [netinet/] [ip_icmp.c] - Blame information for rev 174

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
//==========================================================================
2
//
3
//      sys/netinet/ip_icmp.c
4
//
5
//     
6
//
7
//==========================================================================
8
//####BSDCOPYRIGHTBEGIN####
9
//
10
// -------------------------------------------
11
//
12
// Portions of this software may have been derived from OpenBSD or other sources,
13
// and are covered by the appropriate copyright disclaimers included herein.
14
//
15
// -------------------------------------------
16
//
17
//####BSDCOPYRIGHTEND####
18
//==========================================================================
19
//#####DESCRIPTIONBEGIN####
20
//
21
// Author(s):    gthomas
22
// Contributors: gthomas
23
// Date:         2000-01-10
24
// Purpose:      
25
// Description:  
26
//              
27
//
28
//####DESCRIPTIONEND####
29
//
30
//==========================================================================
31
 
32
 
33
/*      $OpenBSD: ip_icmp.c,v 1.19 1999/12/08 06:50:19 itojun Exp $     */
34
/*      $NetBSD: ip_icmp.c,v 1.19 1996/02/13 23:42:22 christos Exp $    */
35
 
36
/*
37
 * Copyright (c) 1982, 1986, 1988, 1993
38
 *      The Regents of the University of California.  All rights reserved.
39
 *
40
 * Redistribution and use in source and binary forms, with or without
41
 * modification, are permitted provided that the following conditions
42
 * are met:
43
 * 1. Redistributions of source code must retain the above copyright
44
 *    notice, this list of conditions and the following disclaimer.
45
 * 2. Redistributions in binary form must reproduce the above copyright
46
 *    notice, this list of conditions and the following disclaimer in the
47
 *    documentation and/or other materials provided with the distribution.
48
 * 3. All advertising materials mentioning features or use of this software
49
 *    must display the following acknowledgement:
50
 *      This product includes software developed by the University of
51
 *      California, Berkeley and its contributors.
52
 * 4. Neither the name of the University nor the names of its contributors
53
 *    may be used to endorse or promote products derived from this software
54
 *    without specific prior written permission.
55
 *
56
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
57
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
58
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
59
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
60
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
61
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
62
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
63
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
64
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
65
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
66
 * SUCH DAMAGE.
67
 *
68
 *      @(#)ip_icmp.c   8.2 (Berkeley) 1/4/94
69
 */
70
 
71
/*
72
%%% portions-copyright-nrl-95
73
Portions of this software are Copyright 1995-1998 by Randall Atkinson,
74
Ronald Lee, Daniel McDonald, Bao Phan, and Chris Winters. All Rights
75
Reserved. All rights under this copyright have been assigned to the US
76
Naval Research Laboratory (NRL). The NRL Copyright Notice and License
77
Agreement Version 1.1 (January 17, 1995) applies to these portions of the
78
software.
79
You should have received a copy of the license with this software. If you
80
didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>.
81
*/
82
 
83
#include <sys/param.h>
84
#ifndef __ECOS
85
#include <sys/systm.h>
86
#endif
87
#include <sys/malloc.h>
88
#include <sys/mbuf.h>
89
#include <sys/protosw.h>
90
#include <sys/socket.h>
91
#include <sys/time.h>
92
#include <sys/kernel.h>
93
#ifndef __ECOS
94
#include <sys/proc.h>
95
 
96
#include <vm/vm.h>
97
#include <sys/sysctl.h>
98
#endif
99
 
100
#include <net/if.h>
101
#include <net/route.h>
102
 
103
#include <netinet/in.h>
104
#include <netinet/in_systm.h>
105
#include <netinet/in_var.h>
106
#include <netinet/ip.h>
107
#include <netinet/ip_icmp.h>
108
#include <netinet/ip_var.h>
109
#include <netinet/icmp_var.h>
110
 
111
#if 0 /*KAME IPSEC*/
112
#include <netinet6/ipsec.h>
113
#include <netkey/key.h>
114
#include <netkey/key_debug.h>
115
#endif
116
 
117
#include <machine/stdarg.h>
118
 
119
/*
120
 * ICMP routines: error generation, receive packet processing, and
121
 * routines to turnaround packets back to the originator, and
122
 * host table maintenance routines.
123
 */
124
 
125
int     icmpmaskrepl = 0;
126
int     icmpbmcastecho = 0;
127
#ifdef ICMPPRINTFS
128
int     icmpprintfs = 0;
129
#endif
130
 
131
#if 0
132
static int      ip_next_mtu __P((int, int));
133
#else
134
/*static*/ int  ip_next_mtu __P((int, int));
135
#endif
136
 
137
extern  struct protosw inetsw[];
138
 
139
/*
140
 * Generate an error packet of type error
141
 * in response to bad packet ip.
142
 *
143
 * The ip packet inside has ip_off and ip_len in host byte order.
144
 */
145
void
146
icmp_error(n, type, code, dest, destifp)
147
        struct mbuf *n;
148
        int type, code;
149
        n_long dest;
150
        struct ifnet *destifp;
151
{
152
        register struct ip *oip = mtod(n, struct ip *), *nip;
153
        register unsigned oiplen = oip->ip_hl << 2;
154
        register struct icmp *icp;
155
        struct mbuf *m, m0;
156
        unsigned icmplen;
157
 
158
#ifdef ICMPPRINTFS
159
        if (icmpprintfs)
160
                printf("icmp_error(%x, %d, %d)\n", oip, type, code);
161
#endif
162
        if (type != ICMP_REDIRECT)
163
                icmpstat.icps_error++;
164
        /*
165
         * Don't send error if not the first fragment of message.
166
         * Don't error if the old packet protocol was ICMP
167
         * error message, only known informational types.
168
         */
169
        if (oip->ip_off &~ (IP_MF|IP_DF))
170
                goto freeit;
171
        if (oip->ip_p == IPPROTO_ICMP && type != ICMP_REDIRECT &&
172
          n->m_len >= oiplen + ICMP_MINLEN &&
173
          !ICMP_INFOTYPE(((struct icmp *)((caddr_t)oip + oiplen))->icmp_type)) {
174
                icmpstat.icps_oldicmp++;
175
                goto freeit;
176
        }
177
        /* Don't send error in response to a multicast or broadcast packet */
178
        if (n->m_flags & (M_BCAST|M_MCAST))
179
                goto freeit;
180
        /*
181
         * First, formulate icmp message
182
         */
183
        m = m_gethdr(M_DONTWAIT, MT_HEADER);
184
        if (m == NULL)
185
                goto freeit;
186
        icmplen = oiplen + min(8, oip->ip_len);
187
        m->m_len = icmplen + ICMP_MINLEN;
188
        MH_ALIGN(m, m->m_len);
189
        icp = mtod(m, struct icmp *);
190
        if ((u_int)type > ICMP_MAXTYPE)
191
                panic("icmp_error");
192
        icmpstat.icps_outhist[type]++;
193
        icp->icmp_type = type;
194
        if (type == ICMP_REDIRECT)
195
                icp->icmp_gwaddr.s_addr = dest;
196
        else {
197
                icp->icmp_void = 0;
198
                /*
199
                 * The following assignments assume an overlay with the
200
                 * zeroed icmp_void field.
201
                 */
202
                if (type == ICMP_PARAMPROB) {
203
                        icp->icmp_pptr = code;
204
                        code = 0;
205
                } else if (type == ICMP_UNREACH &&
206
                    code == ICMP_UNREACH_NEEDFRAG && destifp)
207
                        icp->icmp_nextmtu = htons(destifp->if_mtu);
208
        }
209
 
210
        icp->icmp_code = code;
211
        bcopy((caddr_t)oip, (caddr_t)&icp->icmp_ip, icmplen);
212
        nip = &icp->icmp_ip;
213
        nip->ip_off = htons(nip->ip_off);
214
        nip->ip_len = htons(nip->ip_len);
215
 
216
        m0.m_next = NULL;                       /* correct nip->ip_sum */
217
        m0.m_data = (char *)nip;
218
        m0.m_len = nip->ip_hl << 2;
219
        nip->ip_sum = 0;
220
        nip->ip_sum = in_cksum(&m0, nip->ip_hl << 2);
221
 
222
        /*
223
         * Now, copy old ip header (without options)
224
         * in front of icmp message.
225
         */
226
        if (m->m_data - sizeof(struct ip) < m->m_pktdat)
227
                panic("icmp len");
228
        m->m_data -= sizeof(struct ip);
229
        m->m_len += sizeof(struct ip);
230
        m->m_pkthdr.len = m->m_len;
231
        m->m_pkthdr.rcvif = n->m_pkthdr.rcvif;
232
        nip = mtod(m, struct ip *);
233
        bcopy((caddr_t)oip, (caddr_t)nip, sizeof(struct ip));
234
        nip->ip_off = htons(nip->ip_off);
235
        nip->ip_len = m->m_len;
236
        nip->ip_hl = sizeof(struct ip) >> 2;
237
        nip->ip_p = IPPROTO_ICMP;
238
        nip->ip_tos = 0;
239
        icmp_reflect(m);
240
 
241
freeit:
242
        m_freem(n);
243
}
244
 
245
static struct sockaddr_in icmpsrc = { sizeof (struct sockaddr_in), AF_INET };
246
static struct sockaddr_in icmpdst = { sizeof (struct sockaddr_in), AF_INET };
247
static struct sockaddr_in icmpgw = { sizeof (struct sockaddr_in), AF_INET };
248
struct sockaddr_in icmpmask = { 8, 0 };
249
 
250
/*
251
 * Process a received ICMP message.
252
 */
253
void
254
#if __STDC__
255
icmp_input(struct mbuf *m, ...)
256
#else
257
icmp_input(m, va_alist)
258
        struct mbuf *m;
259
        va_dcl
260
#endif
261
{
262
        int proto;
263
        register struct icmp *icp;
264
        register struct ip *ip = mtod(m, struct ip *);
265
        int icmplen = ip->ip_len;
266
        register int i;
267
        struct in_ifaddr *ia;
268
        void *(*ctlfunc) __P((int, struct sockaddr *, void *));
269
        int code;
270
        extern u_char ip_protox[];
271
        int hlen;
272
        va_list ap;
273
 
274
        va_start(ap, m);
275
        hlen = va_arg(ap, int);
276
        proto = va_arg(ap, int);
277
        va_end(ap);
278
 
279
        /*
280
         * Locate icmp structure in mbuf, and check
281
         * that not corrupted and of at least minimum length.
282
         */
283
#ifdef ICMPPRINTFS
284
        if (icmpprintfs) {
285
                char buf[4*sizeof "123"];
286
 
287
                strcpy(buf, inet_ntoa(ip->ip_dst));
288
                printf("icmp_input from %s to %s, len %d\n",
289
                        inet_ntoa(ip->ip_src), buf, icmplen);
290
        }
291
#endif
292
        if (icmplen < ICMP_MINLEN) {
293
                icmpstat.icps_tooshort++;
294
                goto freeit;
295
        }
296
        i = hlen + min(icmplen, ICMP_ADVLENMIN);
297
        if (m->m_len < i && (m = m_pullup(m, i)) == 0)  {
298
                icmpstat.icps_tooshort++;
299
                return;
300
        }
301
        ip = mtod(m, struct ip *);
302
        m->m_len -= hlen;
303
        m->m_data += hlen;
304
        icp = mtod(m, struct icmp *);
305
        if (in_cksum(m, icmplen)) {
306
                icmpstat.icps_checksum++;
307
                goto freeit;
308
        }
309
        m->m_len += hlen;
310
        m->m_data -= hlen;
311
 
312
#ifdef ICMPPRINTFS
313
        /*
314
         * Message type specific processing.
315
         */
316
        if (icmpprintfs)
317
                printf("icmp_input, type %d code %d\n", icp->icmp_type,
318
                    icp->icmp_code);
319
#endif
320
#if 0 /*KAME IPSEC*/
321
        /* drop it if it does not match the policy */
322
        if (ipsec4_in_reject(m, NULL)) {
323
                ipsecstat.in_polvio++;
324
                goto freeit;
325
        }
326
#endif
327
        if (icp->icmp_type > ICMP_MAXTYPE)
328
                goto raw;
329
        icmpstat.icps_inhist[icp->icmp_type]++;
330
        code = icp->icmp_code;
331
        switch (icp->icmp_type) {
332
 
333
        case ICMP_UNREACH:
334
                switch (code) {
335
                case ICMP_UNREACH_NET:
336
                case ICMP_UNREACH_HOST:
337
                case ICMP_UNREACH_PROTOCOL:
338
                case ICMP_UNREACH_PORT:
339
                case ICMP_UNREACH_SRCFAIL:
340
                        code += PRC_UNREACH_NET;
341
                        break;
342
 
343
                case ICMP_UNREACH_NEEDFRAG:
344
#if 0 /*NRL INET6*/
345
                        if (icp->icmp_nextmtu) {
346
                                extern int ipv6_trans_mtu
347
                                    __P((struct mbuf **, int, int));
348
                                struct mbuf *m0 = m;
349
 
350
                                /*
351
                                 * Do cool v4-related path MTU, for now,
352
                                 * only v6-in-v4 can handle it.
353
                                 */
354
                                if (icmplen >= ICMP_V6ADVLENMIN &&
355
                                    icmplen >= ICMP_V6ADVLEN(icp) &&
356
                                    icp->icmp_ip.ip_p == IPPROTO_IPV6) {
357
                                        /*
358
                                         * ipv6_trans_mtu returns 1 if
359
                                         * the mbuf is still intact.
360
                                         */
361
                                        if (ipv6_trans_mtu(&m0,icp->icmp_nextmtu,
362
                                            hlen + ICMP_V6ADVLEN(icp))) {
363
                                                m = m0;
364
                                                goto raw;
365
                                        } else
366
                                                return;
367
                                }
368
                        }
369
#endif /* INET6 */
370
                        code = PRC_MSGSIZE;
371
                        break;
372
 
373
                case ICMP_UNREACH_NET_UNKNOWN:
374
                case ICMP_UNREACH_NET_PROHIB:
375
                case ICMP_UNREACH_TOSNET:
376
                        code = PRC_UNREACH_NET;
377
                        break;
378
 
379
                case ICMP_UNREACH_HOST_UNKNOWN:
380
                case ICMP_UNREACH_ISOLATED:
381
                case ICMP_UNREACH_HOST_PROHIB:
382
                case ICMP_UNREACH_TOSHOST:
383
                case ICMP_UNREACH_FILTER_PROHIB:
384
                case ICMP_UNREACH_HOST_PRECEDENCE:
385
                case ICMP_UNREACH_PRECEDENCE_CUTOFF:
386
                        code = PRC_UNREACH_HOST;
387
                        break;
388
 
389
                default:
390
                        goto badcode;
391
                }
392
                goto deliver;
393
 
394
        case ICMP_TIMXCEED:
395
                if (code > 1)
396
                        goto badcode;
397
                code += PRC_TIMXCEED_INTRANS;
398
                goto deliver;
399
 
400
        case ICMP_PARAMPROB:
401
                if (code > 1)
402
                        goto badcode;
403
                code = PRC_PARAMPROB;
404
                goto deliver;
405
 
406
        case ICMP_SOURCEQUENCH:
407
                if (code)
408
                        goto badcode;
409
                code = PRC_QUENCH;
410
        deliver:
411
                /*
412
                 * Problem with datagram; advise higher level routines.
413
                 */
414
                if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp) ||
415
                    icp->icmp_ip.ip_hl < (sizeof(struct ip) >> 2)) {
416
                        icmpstat.icps_badlen++;
417
                        goto freeit;
418
                }
419
                if (IN_MULTICAST(icp->icmp_ip.ip_dst.s_addr))
420
                        goto badcode;
421
                NTOHS(icp->icmp_ip.ip_len);
422
#ifdef INET6
423
                /* Get more contiguous data for a v6 in v4 ICMP message. */
424
                if (icp->icmp_ip.ip_p == IPPROTO_IPV6) {
425
                        if (icmplen < ICMP_V6ADVLENMIN ||
426
                            icmplen < ICMP_V6ADVLEN(icp)) {
427
                                icmpstat.icps_badlen++;
428
                                goto freeit;
429
                        } else {
430
                                if (!(m = m_pullup(m, (ip->ip_hl << 2) +
431
                                    ICMP_V6ADVLEN(icp)))) {
432
                                        icmpstat.icps_tooshort++;
433
                                        return;
434
                                }
435
                                ip = mtod(m, struct ip *);
436
                                icp = (struct icmp *)(m->m_data + (ip->ip_hl << 2));
437
                        }
438
                }
439
#endif /* INET6 */
440
#ifdef ICMPPRINTFS
441
                if (icmpprintfs)
442
                        printf("deliver to protocol %d\n", icp->icmp_ip.ip_p);
443
#endif
444
                icmpsrc.sin_addr = icp->icmp_ip.ip_dst;
445
                /*
446
                 * XXX if the packet contains [IPv4 AH TCP], we can't make a
447
                 * notification to TCP layer.
448
                 */
449
                ctlfunc = inetsw[ip_protox[icp->icmp_ip.ip_p]].pr_ctlinput;
450
                if (ctlfunc)
451
                        (*ctlfunc)(code, sintosa(&icmpsrc), &icp->icmp_ip);
452
                break;
453
 
454
        badcode:
455
                icmpstat.icps_badcode++;
456
                break;
457
 
458
        case ICMP_ECHO:
459
                if (!icmpbmcastecho &&
460
                    (m->m_flags & (M_MCAST | M_BCAST)) != 0) {
461
                        icmpstat.icps_bmcastecho++;
462
                        break;
463
                }
464
                icp->icmp_type = ICMP_ECHOREPLY;
465
                goto reflect;
466
 
467
        case ICMP_TSTAMP:
468
                if (!icmpbmcastecho &&
469
                    (m->m_flags & (M_MCAST | M_BCAST)) != 0) {
470
                        icmpstat.icps_bmcastecho++;
471
                        break;
472
                }
473
                if (icmplen < ICMP_TSLEN) {
474
                        icmpstat.icps_badlen++;
475
                        break;
476
                }
477
                icp->icmp_type = ICMP_TSTAMPREPLY;
478
                icp->icmp_rtime = iptime();
479
                icp->icmp_ttime = icp->icmp_rtime;      /* bogus, do later! */
480
                goto reflect;
481
 
482
        case ICMP_MASKREQ:
483
                if (icmpmaskrepl == 0)
484
                        break;
485
                /*
486
                 * We are not able to respond with all ones broadcast
487
                 * unless we receive it over a point-to-point interface.
488
                 */
489
                if (icmplen < ICMP_MASKLEN) {
490
                        icmpstat.icps_badlen++;
491
                        break;
492
                }
493
                if (ip->ip_dst.s_addr == INADDR_BROADCAST ||
494
                    ip->ip_dst.s_addr == INADDR_ANY)
495
                        icmpdst.sin_addr = ip->ip_src;
496
                else
497
                        icmpdst.sin_addr = ip->ip_dst;
498
                ia = ifatoia(ifaof_ifpforaddr(sintosa(&icmpdst),
499
                    m->m_pkthdr.rcvif));
500
                if (ia == 0)
501
                        break;
502
                icp->icmp_type = ICMP_MASKREPLY;
503
                icp->icmp_mask = ia->ia_sockmask.sin_addr.s_addr;
504
                if (ip->ip_src.s_addr == 0) {
505
                        if (ia->ia_ifp->if_flags & IFF_BROADCAST)
506
                                ip->ip_src = ia->ia_broadaddr.sin_addr;
507
                        else if (ia->ia_ifp->if_flags & IFF_POINTOPOINT)
508
                                ip->ip_src = ia->ia_dstaddr.sin_addr;
509
                }
510
reflect:
511
                ip->ip_len += hlen;     /* since ip_input deducts this */
512
                icmpstat.icps_reflect++;
513
                icmpstat.icps_outhist[icp->icmp_type]++;
514
                icmp_reflect(m);
515
                return;
516
 
517
        case ICMP_REDIRECT:
518
                if (code > 3)
519
                        goto badcode;
520
                if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp) ||
521
                    icp->icmp_ip.ip_hl < (sizeof(struct ip) >> 2)) {
522
                        icmpstat.icps_badlen++;
523
                        break;
524
                }
525
                /*
526
                 * Short circuit routing redirects to force
527
                 * immediate change in the kernel's routing
528
                 * tables.  The message is also handed to anyone
529
                 * listening on a raw socket (e.g. the routing
530
                 * daemon for use in updating its tables).
531
                 */
532
                icmpgw.sin_addr = ip->ip_src;
533
                icmpdst.sin_addr = icp->icmp_gwaddr;
534
#ifdef  ICMPPRINTFS
535
                if (icmpprintfs) {
536
                        char buf[4 * sizeof "123"];
537
                        strcpy(buf, inet_ntoa(icp->icmp_ip.ip_dst));
538
 
539
                        printf("redirect dst %s to %s\n",
540
                            buf, inet_ntoa(icp->icmp_gwaddr));
541
                }
542
#endif
543
                icmpsrc.sin_addr = icp->icmp_ip.ip_dst;
544
                rtredirect(sintosa(&icmpsrc), sintosa(&icmpdst),
545
                    (struct sockaddr *)0, RTF_GATEWAY | RTF_HOST,
546
                    sintosa(&icmpgw), (struct rtentry **)0);
547
                pfctlinput(PRC_REDIRECT_HOST, sintosa(&icmpsrc));
548
#if 0 /*KAME IPSEC*/
549
                key_sa_routechange((struct sockaddr *)&icmpsrc);
550
#endif
551
                break;
552
 
553
        /*
554
         * No kernel processing for the following;
555
         * just fall through to send to raw listener.
556
         */
557
        case ICMP_ECHOREPLY:
558
        case ICMP_ROUTERADVERT:
559
        case ICMP_ROUTERSOLICIT:
560
        case ICMP_TSTAMPREPLY:
561
        case ICMP_IREQREPLY:
562
        case ICMP_MASKREPLY:
563
        default:
564
                break;
565
        }
566
 
567
raw:
568
        rip_input(m, hlen, proto);
569
        return;
570
 
571
freeit:
572
        m_freem(m);
573
}
574
 
575
/*
576
 * Reflect the ip packet back to the source
577
 */
578
void
579
icmp_reflect(m)
580
        struct mbuf *m;
581
{
582
        register struct ip *ip = mtod(m, struct ip *);
583
        register struct in_ifaddr *ia;
584
        struct in_addr t;
585
        struct mbuf *opts = 0;
586
        int optlen = (ip->ip_hl << 2) - sizeof(struct ip);
587
 
588
        if (!in_canforward(ip->ip_src) &&
589
            ((ip->ip_src.s_addr & IN_CLASSA_NET) !=
590
             htonl(IN_LOOPBACKNET << IN_CLASSA_NSHIFT))) {
591
                m_freem(m);     /* Bad return address */
592
                goto done;      /* ip_output() will check for broadcast */
593
        }
594
        t = ip->ip_dst;
595
        ip->ip_dst = ip->ip_src;
596
        /*
597
         * If the incoming packet was addressed directly to us,
598
         * use dst as the src for the reply.  Otherwise (broadcast
599
         * or anonymous), use the address which corresponds
600
         * to the incoming interface.
601
         */
602
        for (ia = in_ifaddr.tqh_first; ia; ia = ia->ia_list.tqe_next) {
603
                if (t.s_addr == ia->ia_addr.sin_addr.s_addr)
604
                        break;
605
                if ((ia->ia_ifp->if_flags & IFF_BROADCAST) &&
606
                    t.s_addr == ia->ia_broadaddr.sin_addr.s_addr)
607
                        break;
608
        }
609
        icmpdst.sin_addr = t;
610
        if (ia == (struct in_ifaddr *)0)
611
                ia = ifatoia(ifaof_ifpforaddr(sintosa(&icmpdst),
612
                    m->m_pkthdr.rcvif));
613
        /*
614
         * The following happens if the packet was not addressed to us,
615
         * and was received on an interface with no IP address.
616
         */
617
        if (ia == (struct in_ifaddr *)0)
618
                ia = in_ifaddr.tqh_first;
619
        t = ia->ia_addr.sin_addr;
620
        ip->ip_src = t;
621
        ip->ip_ttl = MAXTTL;
622
 
623
        if (optlen > 0) {
624
                register u_char *cp;
625
                int opt, cnt;
626
                u_int len;
627
 
628
                /*
629
                 * Retrieve any source routing from the incoming packet;
630
                 * add on any record-route or timestamp options.
631
                 */
632
                cp = (u_char *) (ip + 1);
633
                if ((opts = ip_srcroute()) == 0 &&
634
                    (opts = m_gethdr(M_DONTWAIT, MT_HEADER))) {
635
                        opts->m_len = sizeof(struct in_addr);
636
                        mtod(opts, struct in_addr *)->s_addr = 0;
637
                }
638
                if (opts) {
639
#ifdef ICMPPRINTFS
640
                    if (icmpprintfs)
641
                            printf("icmp_reflect optlen %d rt %d => ",
642
                                optlen, opts->m_len);
643
#endif
644
                    for (cnt = optlen; cnt > 0; cnt -= len, cp += len) {
645
                            opt = cp[IPOPT_OPTVAL];
646
                            if (opt == IPOPT_EOL)
647
                                    break;
648
                            if (opt == IPOPT_NOP)
649
                                    len = 1;
650
                            else {
651
                                    len = cp[IPOPT_OLEN];
652
                                    if (len <= 0 || len > cnt)
653
                                            break;
654
                            }
655
                            /*
656
                             * Should check for overflow, but it "can't happen"
657
                             */
658
                            if (opt == IPOPT_RR || opt == IPOPT_TS ||
659
                                opt == IPOPT_SECURITY) {
660
                                    bcopy((caddr_t)cp,
661
                                        mtod(opts, caddr_t) + opts->m_len, len);
662
                                    opts->m_len += len;
663
                            }
664
                    }
665
                    /* Terminate & pad, if necessary */
666
                    if ((cnt = opts->m_len % 4) != 0) {
667
                            for (; cnt < 4; cnt++) {
668
                                    *(mtod(opts, caddr_t) + opts->m_len) =
669
                                        IPOPT_EOL;
670
                                    opts->m_len++;
671
                            }
672
                    }
673
#ifdef ICMPPRINTFS
674
                    if (icmpprintfs)
675
                            printf("%d\n", opts->m_len);
676
#endif
677
                }
678
                /*
679
                 * Now strip out original options by copying rest of first
680
                 * mbuf's data back, and adjust the IP length.
681
                 */
682
                ip->ip_len -= optlen;
683
                ip->ip_hl = sizeof(struct ip) >> 2;
684
                m->m_len -= optlen;
685
                if (m->m_flags & M_PKTHDR)
686
                        m->m_pkthdr.len -= optlen;
687
                optlen += sizeof(struct ip);
688
                bcopy((caddr_t)ip + optlen, (caddr_t)(ip + 1),
689
                         (unsigned)(m->m_len - sizeof(struct ip)));
690
        }
691
        m->m_flags &= ~(M_BCAST|M_MCAST);
692
        icmp_send(m, opts);
693
done:
694
        if (opts)
695
                (void)m_free(opts);
696
}
697
 
698
/*
699
 * Send an icmp packet back to the ip level,
700
 * after supplying a checksum.
701
 */
702
void
703
icmp_send(m, opts)
704
        register struct mbuf *m;
705
        struct mbuf *opts;
706
{
707
        register struct ip *ip = mtod(m, struct ip *);
708
        register int hlen;
709
        register struct icmp *icp;
710
 
711
        hlen = ip->ip_hl << 2;
712
        m->m_data += hlen;
713
        m->m_len -= hlen;
714
        icp = mtod(m, struct icmp *);
715
        icp->icmp_cksum = 0;
716
        icp->icmp_cksum = in_cksum(m, ip->ip_len - hlen);
717
        m->m_data -= hlen;
718
        m->m_len += hlen;
719
#ifdef ICMPPRINTFS
720
        if (icmpprintfs) {
721
                char buf[4 * sizeof "123"];
722
 
723
                strcpy(buf, inet_ntoa(ip->ip_dst));
724
                printf("icmp_send dst %s src %s\n",
725
                    buf, inet_ntoa(ip->ip_src));
726
        }
727
#endif
728
#if 0 /*KAME IPSEC*/
729
        m->m_pkthdr.rcvif = NULL;
730
#endif /*IPSEC*/
731
        (void) ip_output(m, opts, NULL, 0, NULL, NULL);
732
}
733
 
734
n_time
735
iptime()
736
{
737
        struct timeval atv;
738
        u_long t;
739
 
740
        microtime(&atv);
741
        t = (atv.tv_sec % (24*60*60)) * 1000 + atv.tv_usec / 1000;
742
        return (htonl(t));
743
}
744
 
745
#ifdef CYGPKG_NET_SYSCTL
746
int
747
icmp_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
748
        int *name;
749
        u_int namelen;
750
        void *oldp;
751
        size_t *oldlenp;
752
        void *newp;
753
        size_t newlen;
754
{
755
 
756
        /* All sysctl names at this level are terminal. */
757
        if (namelen != 1)
758
                return (ENOTDIR);
759
 
760
        switch (name[0]) {
761
        case ICMPCTL_MASKREPL:
762
                return (sysctl_int(oldp, oldlenp, newp, newlen, &icmpmaskrepl));
763
        case ICMPCTL_BMCASTECHO:
764
                return (sysctl_int(oldp, oldlenp, newp, newlen, &icmpbmcastecho));
765
        default:
766
                return (ENOPROTOOPT);
767
        }
768
        /* NOTREACHED */
769
}
770
#endif // CYGPKG_NET_SYSCTL

powered by: WebSVN 2.1.0

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