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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [net/] [tcpip/] [current/] [src/] [sys/] [netinet/] [ip_icmp.c] - Blame information for rev 786

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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