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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [rtems/] [c/] [src/] [libnetworking/] [netinet/] [ip_output.c] - Blame information for rev 773

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

Line No. Rev Author Line
1 30 unneback
/*
2
 * Copyright (c) 1982, 1986, 1988, 1990, 1993
3
 *      The Regents of the University of California.  All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 * 1. Redistributions of source code must retain the above copyright
9
 *    notice, this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright
11
 *    notice, this list of conditions and the following disclaimer in the
12
 *    documentation and/or other materials provided with the distribution.
13
 * 3. All advertising materials mentioning features or use of this software
14
 *    must display the following acknowledgement:
15
 *      This product includes software developed by the University of
16
 *      California, Berkeley and its contributors.
17
 * 4. Neither the name of the University nor the names of its contributors
18
 *    may be used to endorse or promote products derived from this software
19
 *    without specific prior written permission.
20
 *
21
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31
 * SUCH DAMAGE.
32
 *
33
 *      @(#)ip_output.c 8.3 (Berkeley) 1/21/94
34
 *      $Id: ip_output.c,v 1.2 2001-09-27 12:01:56 chris Exp $
35
 */
36
 
37
#define _IP_VHL
38
 
39
#include <sys/param.h>
40
#include <sys/queue.h>
41
#include <sys/systm.h>
42
#include <sys/malloc.h>
43
#include <sys/mbuf.h>
44
#include <sys/errno.h>
45
#include <sys/protosw.h>
46
#include <sys/socket.h>
47
#include <sys/socketvar.h>
48
 
49
#include <net/if.h>
50
#include <net/route.h>
51
 
52
#include <netinet/in.h>
53
#include <netinet/in_systm.h>
54
#include <netinet/ip.h>
55
#include <netinet/in_pcb.h>
56
#include <netinet/in_var.h>
57
#include <netinet/ip_var.h>
58
 
59
#ifdef vax
60
#include <machine/mtpr.h>
61
#endif
62
#include <machine/in_cksum.h>
63
 
64
#if !defined(COMPAT_IPFW) || COMPAT_IPFW == 1
65
#undef COMPAT_IPFW
66
#define COMPAT_IPFW 1
67
#else
68
#undef COMPAT_IPFW
69
#endif
70
 
71
u_short ip_id;
72
 
73
static struct mbuf *ip_insertoptions __P((struct mbuf *, struct mbuf *, int *));
74
static void     ip_mloopback
75
        __P((struct ifnet *, struct mbuf *, struct sockaddr_in *, int));
76
static int      ip_getmoptions
77
        __P((int, struct ip_moptions *, struct mbuf **));
78
static int      ip_optcopy __P((struct ip *, struct ip *));
79
static int      ip_pcbopts __P((struct mbuf **, struct mbuf *));
80
static int      ip_setmoptions
81
        __P((int, struct ip_moptions **, struct mbuf *));
82
 
83
extern  struct protosw inetsw[];
84
 
85
/*
86
 * IP output.  The packet in mbuf chain m contains a skeletal IP
87
 * header (with len, off, ttl, proto, tos, src, dst).
88
 * The mbuf chain containing the packet will be freed.
89
 * The mbuf opt, if present, will not be freed.
90
 */
91
int
92
ip_output(m0, opt, ro, flags, imo)
93
        struct mbuf *m0;
94
        struct mbuf *opt;
95
        struct route *ro;
96
        int flags;
97
        struct ip_moptions *imo;
98
{
99
        struct ip *ip, *mhip;
100
        struct ifnet *ifp;
101
        struct mbuf *m = m0;
102
        int hlen = sizeof (struct ip);
103
        int len, off, error = 0;
104
        struct sockaddr_in *dst;
105
        struct in_ifaddr *ia;
106
        int isbroadcast;
107
 
108
#ifdef  DIAGNOSTIC
109
        if ((m->m_flags & M_PKTHDR) == 0)
110
                panic("ip_output no HDR");
111
        if (!ro)
112
                panic("ip_output no route, proto = %d",
113
                      mtod(m, struct ip *)->ip_p);
114
#endif
115
        if (opt) {
116
                m = ip_insertoptions(m, opt, &len);
117
                hlen = len;
118
        }
119
        ip = mtod(m, struct ip *);
120
        /*
121
         * Fill in IP header.
122
         */
123
        if ((flags & (IP_FORWARDING|IP_RAWOUTPUT)) == 0) {
124
                ip->ip_vhl = IP_MAKE_VHL(IPVERSION, hlen >> 2);
125
                ip->ip_off &= IP_DF;
126
                ip->ip_id = htons(ip_id++);
127
                ipstat.ips_localout++;
128
        } else {
129
                hlen = IP_VHL_HL(ip->ip_vhl) << 2;
130
        }
131
 
132
        dst = (struct sockaddr_in *)&ro->ro_dst;
133
        /*
134
         * If there is a cached route,
135
         * check that it is to the same destination
136
         * and is still up.  If not, free it and try again.
137
         */
138
        if (ro->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 ||
139
           dst->sin_addr.s_addr != ip->ip_dst.s_addr)) {
140
                RTFREE(ro->ro_rt);
141
                ro->ro_rt = (struct rtentry *)0;
142
        }
143
        if (ro->ro_rt == 0) {
144
                dst->sin_family = AF_INET;
145
                dst->sin_len = sizeof(*dst);
146
                dst->sin_addr = ip->ip_dst;
147
        }
148
        /*
149
         * If routing to interface only,
150
         * short circuit routing lookup.
151
         */
152
#define ifatoia(ifa)    ((struct in_ifaddr *)(ifa))
153
#define sintosa(sin)    ((struct sockaddr *)(sin))
154
        if (flags & IP_ROUTETOIF) {
155
                if ((ia = ifatoia(ifa_ifwithdstaddr(sintosa(dst)))) == 0 &&
156
                    (ia = ifatoia(ifa_ifwithnet(sintosa(dst)))) == 0) {
157
                        ipstat.ips_noroute++;
158
                        error = ENETUNREACH;
159
                        goto bad;
160
                }
161
                ifp = ia->ia_ifp;
162
                ip->ip_ttl = 1;
163
                isbroadcast = in_broadcast(dst->sin_addr, ifp);
164
        } else {
165
                /*
166
                 * If this is the case, we probably don't want to allocate
167
                 * a protocol-cloned route since we didn't get one from the
168
                 * ULP.  This lets TCP do its thing, while not burdening
169
                 * forwarding or ICMP with the overhead of cloning a route.
170
                 * Of course, we still want to do any cloning requested by
171
                 * the link layer, as this is probably required in all cases
172
                 * for correct operation (as it is for ARP).
173
                 */
174
                if (ro->ro_rt == 0)
175
                        rtalloc_ign(ro, RTF_PRCLONING);
176
                if (ro->ro_rt == 0) {
177
                        ipstat.ips_noroute++;
178
                        error = EHOSTUNREACH;
179
                        goto bad;
180
                }
181
                ia = ifatoia(ro->ro_rt->rt_ifa);
182
                ifp = ro->ro_rt->rt_ifp;
183
                ro->ro_rt->rt_use++;
184
                if (ro->ro_rt->rt_flags & RTF_GATEWAY)
185
                        dst = (struct sockaddr_in *)ro->ro_rt->rt_gateway;
186
                if (ro->ro_rt->rt_flags & RTF_HOST)
187
                        isbroadcast = (ro->ro_rt->rt_flags & RTF_BROADCAST);
188
                else
189
                        isbroadcast = in_broadcast(dst->sin_addr, ifp);
190
        }
191
        if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) {
192
                struct in_multi *inm;
193
 
194
                m->m_flags |= M_MCAST;
195
                /*
196
                 * IP destination address is multicast.  Make sure "dst"
197
                 * still points to the address in "ro".  (It may have been
198
                 * changed to point to a gateway address, above.)
199
                 */
200
                dst = (struct sockaddr_in *)&ro->ro_dst;
201
                /*
202
                 * See if the caller provided any multicast options
203
                 */
204
                if (imo != NULL) {
205
                        ip->ip_ttl = imo->imo_multicast_ttl;
206
                        if (imo->imo_multicast_ifp != NULL)
207
                                ifp = imo->imo_multicast_ifp;
208
                        if (imo->imo_multicast_vif != -1)
209
                                ip->ip_src.s_addr =
210
                                    ip_mcast_src(imo->imo_multicast_vif);
211
                } else
212
                        ip->ip_ttl = IP_DEFAULT_MULTICAST_TTL;
213
                /*
214
                 * Confirm that the outgoing interface supports multicast.
215
                 */
216
                if ((imo == NULL) || (imo->imo_multicast_vif == -1)) {
217
                        if ((ifp->if_flags & IFF_MULTICAST) == 0) {
218
                                ipstat.ips_noroute++;
219
                                error = ENETUNREACH;
220
                                goto bad;
221
                        }
222
                }
223
                /*
224
                 * If source address not specified yet, use address
225
                 * of outgoing interface.
226
                 */
227
                if (ip->ip_src.s_addr == INADDR_ANY) {
228
                        register struct in_ifaddr *ia;
229
 
230
                        for (ia = in_ifaddr; ia; ia = ia->ia_next)
231
                                if (ia->ia_ifp == ifp) {
232
                                        ip->ip_src = IA_SIN(ia)->sin_addr;
233
                                        break;
234
                                }
235
                }
236
 
237
                IN_LOOKUP_MULTI(ip->ip_dst, ifp, inm);
238
                if (inm != NULL &&
239
                   (imo == NULL || imo->imo_multicast_loop)) {
240
                        /*
241
                         * If we belong to the destination multicast group
242
                         * on the outgoing interface, and the caller did not
243
                         * forbid loopback, loop back a copy.
244
                         */
245
                        ip_mloopback(ifp, m, dst, hlen);
246
                }
247
                else {
248
                        /*
249
                         * If we are acting as a multicast router, perform
250
                         * multicast forwarding as if the packet had just
251
                         * arrived on the interface to which we are about
252
                         * to send.  The multicast forwarding function
253
                         * recursively calls this function, using the
254
                         * IP_FORWARDING flag to prevent infinite recursion.
255
                         *
256
                         * Multicasts that are looped back by ip_mloopback(),
257
                         * above, will be forwarded by the ip_input() routine,
258
                         * if necessary.
259
                         */
260
                        if (ip_mrouter && (flags & IP_FORWARDING) == 0) {
261
                                /*
262
                                 * Check if rsvp daemon is running. If not, don't
263
                                 * set ip_moptions. This ensures that the packet
264
                                 * is multicast and not just sent down one link
265
                                 * as prescribed by rsvpd.
266
                                 */
267
                                if (!rsvp_on)
268
                                  imo = NULL;
269
                                if (ip_mforward(ip, ifp, m, imo) != 0) {
270
                                        m_freem(m);
271
                                        goto done;
272
                                }
273
                        }
274
                }
275
 
276
                /*
277
                 * Multicasts with a time-to-live of zero may be looped-
278
                 * back, above, but must not be transmitted on a network.
279
                 * Also, multicasts addressed to the loopback interface
280
                 * are not sent -- the above call to ip_mloopback() will
281
                 * loop back a copy if this host actually belongs to the
282
                 * destination group on the loopback interface.
283
                 */
284
                if (ip->ip_ttl == 0 || ifp->if_flags & IFF_LOOPBACK) {
285
                        m_freem(m);
286
                        goto done;
287
                }
288
 
289
                goto sendit;
290
        }
291
#ifndef notdef
292
        /*
293
         * If source address not specified yet, use address
294
         * of outgoing interface.
295
         */
296
        if (ip->ip_src.s_addr == INADDR_ANY)
297
                ip->ip_src = IA_SIN(ia)->sin_addr;
298
#endif
299
        /*
300
         * Verify that we have any chance at all of being able to queue
301
         *      the packet or packet fragments
302
         */
303
        if ((ifp->if_snd.ifq_len + ip->ip_len / ifp->if_mtu + 1) >=
304
                ifp->if_snd.ifq_maxlen) {
305
                        error = ENOBUFS;
306
                        goto bad;
307
        }
308
 
309
        /*
310
         * Look for broadcast address and
311
         * and verify user is allowed to send
312
         * such a packet.
313
         */
314
        if (isbroadcast) {
315
                if ((ifp->if_flags & IFF_BROADCAST) == 0) {
316
                        error = EADDRNOTAVAIL;
317
                        goto bad;
318
                }
319
                if ((flags & IP_ALLOWBROADCAST) == 0) {
320
                        error = EACCES;
321
                        goto bad;
322
                }
323
                /* don't allow broadcast messages to be fragmented */
324
                if ((u_short)ip->ip_len > ifp->if_mtu) {
325
                        error = EMSGSIZE;
326
                        goto bad;
327
                }
328
                m->m_flags |= M_BCAST;
329
        } else {
330
                m->m_flags &= ~M_BCAST;
331
        }
332
 
333
sendit:
334
        /*
335
         * IpHack's section.
336
         * - Xlate: translate packet's addr/port (NAT).
337
         * - Firewall: deny/allow/etc.
338
         * - Wrap: fake packet's addr/port <unimpl.>
339
         * - Encapsulate: put it in another IP and send out. <unimp.>
340
         */
341
 
342
#ifdef COMPAT_IPFW
343
        if (ip_nat_ptr && !(*ip_nat_ptr)(&ip, &m, ifp, IP_NAT_OUT)) {
344
                error = EACCES;
345
                goto done;
346
        }
347
 
348
        /*
349
         * Check with the firewall...
350
         */
351
        if (ip_fw_chk_ptr) {
352
#ifdef IPDIVERT
353
                ip_divert_port = (*ip_fw_chk_ptr)(&ip,
354
                    hlen, ifp, ip_divert_ignore, &m);
355
                ip_divert_ignore = 0;
356
                if (ip_divert_port) {           /* Divert packet */
357
                        (*inetsw[ip_protox[IPPROTO_DIVERT]].pr_input)(m, 0);
358
                        goto done;
359
                }
360
#else
361
                /* If ipfw says divert, we have to just drop packet */
362
                if ((*ip_fw_chk_ptr)(&ip, hlen, ifp, 0, &m)) {
363
                        m_freem(m);
364
                        goto done;
365
                }
366
#endif
367
                if (!m) {
368
                        error = EACCES;
369
                        goto done;
370
                }
371
        }
372
#endif /* COMPAT_IPFW */
373
 
374
        /*
375
         * If small enough for interface, can just send directly.
376
         */
377
        if ((u_short)ip->ip_len <= ifp->if_mtu) {
378
                ip->ip_len = htons((u_short)ip->ip_len);
379
                ip->ip_off = htons((u_short)ip->ip_off);
380
                ip->ip_sum = 0;
381
                if (ip->ip_vhl == IP_VHL_BORING) {
382
                        ip->ip_sum = in_cksum_hdr(ip);
383
                } else {
384
                        ip->ip_sum = in_cksum(m, hlen);
385
                }
386
                error = (*ifp->if_output)(ifp, m,
387
                                (struct sockaddr *)dst, ro->ro_rt);
388
                goto done;
389
        }
390
        /*
391
         * Too large for interface; fragment if possible.
392
         * Must be able to put at least 8 bytes per fragment.
393
         */
394
        if (ip->ip_off & IP_DF) {
395
                error = EMSGSIZE;
396
                /*
397
                 * This case can happen if the user changed the MTU
398
                 * of an interface after enabling IP on it.  Because
399
                 * most netifs don't keep track of routes pointing to
400
                 * them, there is no way for one to update all its
401
                 * routes when the MTU is changed.
402
                 */
403
                if ((ro->ro_rt->rt_flags & (RTF_UP | RTF_HOST))
404
                    && !(ro->ro_rt->rt_rmx.rmx_locks & RTV_MTU)
405
                    && (ro->ro_rt->rt_rmx.rmx_mtu > ifp->if_mtu)) {
406
                        ro->ro_rt->rt_rmx.rmx_mtu = ifp->if_mtu;
407
                }
408
                ipstat.ips_cantfrag++;
409
                goto bad;
410
        }
411
        len = (ifp->if_mtu - hlen) &~ 7;
412
        if (len < 8) {
413
                error = EMSGSIZE;
414
                goto bad;
415
        }
416
 
417
    {
418
        int mhlen, firstlen = len;
419
        struct mbuf **mnext = &m->m_nextpkt;
420
 
421
        /*
422
         * Loop through length of segment after first fragment,
423
         * make new header and copy data of each part and link onto chain.
424
         */
425
        m0 = m;
426
        mhlen = sizeof (struct ip);
427
        for (off = hlen + len; off < (u_short)ip->ip_len; off += len) {
428
                MGETHDR(m, M_DONTWAIT, MT_HEADER);
429
                if (m == 0) {
430
                        error = ENOBUFS;
431
                        ipstat.ips_odropped++;
432
                        goto sendorfree;
433
                }
434
                m->m_data += max_linkhdr;
435
                mhip = mtod(m, struct ip *);
436
                *mhip = *ip;
437
                if (hlen > sizeof (struct ip)) {
438
                        mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip);
439
                        mhip->ip_vhl = IP_MAKE_VHL(IPVERSION, mhlen >> 2);
440
                }
441
                m->m_len = mhlen;
442
                mhip->ip_off = ((off - hlen) >> 3) + (ip->ip_off & ~IP_MF);
443
                if (ip->ip_off & IP_MF)
444
                        mhip->ip_off |= IP_MF;
445
                if (off + len >= (u_short)ip->ip_len)
446
                        len = (u_short)ip->ip_len - off;
447
                else
448
                        mhip->ip_off |= IP_MF;
449
                mhip->ip_len = htons((u_short)(len + mhlen));
450
                m->m_next = m_copy(m0, off, len);
451
                if (m->m_next == 0) {
452
                        (void) m_free(m);
453
                        error = ENOBUFS;        /* ??? */
454
                        ipstat.ips_odropped++;
455
                        goto sendorfree;
456
                }
457
                m->m_pkthdr.len = mhlen + len;
458
                m->m_pkthdr.rcvif = (struct ifnet *)0;
459
                mhip->ip_off = htons((u_short)mhip->ip_off);
460
                mhip->ip_sum = 0;
461
                if (mhip->ip_vhl == IP_VHL_BORING) {
462
                        mhip->ip_sum = in_cksum_hdr(mhip);
463
                } else {
464
                        mhip->ip_sum = in_cksum(m, mhlen);
465
                }
466
                *mnext = m;
467
                mnext = &m->m_nextpkt;
468
                ipstat.ips_ofragments++;
469
        }
470
        /*
471
         * Update first fragment by trimming what's been copied out
472
         * and updating header, then send each fragment (in order).
473
         */
474
        m = m0;
475
        m_adj(m, hlen + firstlen - (u_short)ip->ip_len);
476
        m->m_pkthdr.len = hlen + firstlen;
477
        ip->ip_len = htons((u_short)m->m_pkthdr.len);
478
        ip->ip_off = htons((u_short)(ip->ip_off | IP_MF));
479
        ip->ip_sum = 0;
480
        if (ip->ip_vhl == IP_VHL_BORING) {
481
                ip->ip_sum = in_cksum_hdr(ip);
482
        } else {
483
                ip->ip_sum = in_cksum(m, hlen);
484
        }
485
sendorfree:
486
        for (m = m0; m; m = m0) {
487
                m0 = m->m_nextpkt;
488
                m->m_nextpkt = 0;
489
                if (error == 0)
490
                        error = (*ifp->if_output)(ifp, m,
491
                            (struct sockaddr *)dst, ro->ro_rt);
492
                else
493
                        m_freem(m);
494
        }
495
 
496
        if (error == 0)
497
                ipstat.ips_fragmented++;
498
    }
499
done:
500
        return (error);
501
bad:
502
        m_freem(m0);
503
        goto done;
504
}
505
 
506
/*
507
 * Insert IP options into preformed packet.
508
 * Adjust IP destination as required for IP source routing,
509
 * as indicated by a non-zero in_addr at the start of the options.
510
 *
511
 * XXX This routine assumes that the packet has no options in place.
512
 */
513
static struct mbuf *
514
ip_insertoptions(m, opt, phlen)
515
        register struct mbuf *m;
516
        struct mbuf *opt;
517
        int *phlen;
518
{
519
        register struct ipoption *p = mtod(opt, struct ipoption *);
520
        struct mbuf *n;
521
        register struct ip *ip = mtod(m, struct ip *);
522
        unsigned optlen;
523
 
524
        optlen = opt->m_len - sizeof(p->ipopt_dst);
525
        if (optlen + (u_short)ip->ip_len > IP_MAXPACKET)
526
                return (m);             /* XXX should fail */
527
        if (p->ipopt_dst.s_addr)
528
                ip->ip_dst = p->ipopt_dst;
529
        if (m->m_flags & M_EXT || m->m_data - optlen < m->m_pktdat) {
530
                MGETHDR(n, M_DONTWAIT, MT_HEADER);
531
                if (n == 0)
532
                        return (m);
533
                n->m_pkthdr.len = m->m_pkthdr.len + optlen;
534
                m->m_len -= sizeof(struct ip);
535
                m->m_data += sizeof(struct ip);
536
                n->m_next = m;
537
                m = n;
538
                m->m_len = optlen + sizeof(struct ip);
539
                m->m_data += max_linkhdr;
540
                (void)memcpy(mtod(m, void *), ip, sizeof(struct ip));
541
        } else {
542
                m->m_data -= optlen;
543
                m->m_len += optlen;
544
                m->m_pkthdr.len += optlen;
545
                ovbcopy((caddr_t)ip, mtod(m, caddr_t), sizeof(struct ip));
546
        }
547
        ip = mtod(m, struct ip *);
548
        bcopy(p->ipopt_list, ip + 1, optlen);
549
        *phlen = sizeof(struct ip) + optlen;
550
        ip->ip_vhl = IP_MAKE_VHL(IPVERSION, *phlen >> 2);
551
        ip->ip_len += optlen;
552
        return (m);
553
}
554
 
555
/*
556
 * Copy options from ip to jp,
557
 * omitting those not copied during fragmentation.
558
 */
559
static int
560
ip_optcopy(ip, jp)
561
        struct ip *ip, *jp;
562
{
563
        register u_char *cp, *dp;
564
        int opt, optlen, cnt;
565
 
566
        cp = (u_char *)(ip + 1);
567
        dp = (u_char *)(jp + 1);
568
        cnt = (IP_VHL_HL(ip->ip_vhl) << 2) - sizeof (struct ip);
569
        for (; cnt > 0; cnt -= optlen, cp += optlen) {
570
                opt = cp[0];
571
                if (opt == IPOPT_EOL)
572
                        break;
573
                if (opt == IPOPT_NOP) {
574
                        /* Preserve for IP mcast tunnel's LSRR alignment. */
575
                        *dp++ = IPOPT_NOP;
576
                        optlen = 1;
577
                        continue;
578
                } else
579
                        optlen = cp[IPOPT_OLEN];
580
                /* bogus lengths should have been caught by ip_dooptions */
581
                if (optlen > cnt)
582
                        optlen = cnt;
583
                if (IPOPT_COPIED(opt)) {
584
                        bcopy(cp, dp, optlen);
585
                        dp += optlen;
586
                }
587
        }
588
        for (optlen = dp - (u_char *)(jp+1); optlen & 0x3; optlen++)
589
                *dp++ = IPOPT_EOL;
590
        return (optlen);
591
}
592
 
593
/*
594
 * IP socket option processing.
595
 */
596
int
597
ip_ctloutput(op, so, level, optname, mp)
598
        int op;
599
        struct socket *so;
600
        int level, optname;
601
        struct mbuf **mp;
602
{
603
        register struct inpcb *inp = sotoinpcb(so);
604
        register struct mbuf *m = *mp;
605
        register int optval = 0;
606
        int error = 0;
607
 
608
        if (level != IPPROTO_IP) {
609
                error = EINVAL;
610
                if (op == PRCO_SETOPT && *mp)
611
                        (void) m_free(*mp);
612
        } else switch (op) {
613
 
614
        case PRCO_SETOPT:
615
                switch (optname) {
616
                case IP_OPTIONS:
617
#ifdef notyet
618
                case IP_RETOPTS:
619
                        return (ip_pcbopts(optname, &inp->inp_options, m));
620
#else
621
                        return (ip_pcbopts(&inp->inp_options, m));
622
#endif
623
 
624
                case IP_TOS:
625
                case IP_TTL:
626
                case IP_RECVOPTS:
627
                case IP_RECVRETOPTS:
628
                case IP_RECVDSTADDR:
629
                case IP_RECVIF:
630
                        if (m == 0 || m->m_len != sizeof(int))
631
                                error = EINVAL;
632
                        else {
633
                                optval = *mtod(m, int *);
634
                                switch (optname) {
635
 
636
                                case IP_TOS:
637
                                        inp->inp_ip_tos = optval;
638
                                        break;
639
 
640
                                case IP_TTL:
641
                                        inp->inp_ip_ttl = optval;
642
                                        break;
643
#define OPTSET(bit) \
644
        if (optval) \
645
                inp->inp_flags |= bit; \
646
        else \
647
                inp->inp_flags &= ~bit;
648
 
649
                                case IP_RECVOPTS:
650
                                        OPTSET(INP_RECVOPTS);
651
                                        break;
652
 
653
                                case IP_RECVRETOPTS:
654
                                        OPTSET(INP_RECVRETOPTS);
655
                                        break;
656
 
657
                                case IP_RECVDSTADDR:
658
                                        OPTSET(INP_RECVDSTADDR);
659
                                        break;
660
 
661
                                case IP_RECVIF:
662
                                        OPTSET(INP_RECVIF);
663
                                        break;
664
                                }
665
                        }
666
                        break;
667
#undef OPTSET
668
 
669
                case IP_MULTICAST_IF:
670
                case IP_MULTICAST_VIF:
671
                case IP_MULTICAST_TTL:
672
                case IP_MULTICAST_LOOP:
673
                case IP_ADD_MEMBERSHIP:
674
                case IP_DROP_MEMBERSHIP:
675
                        error = ip_setmoptions(optname, &inp->inp_moptions, m);
676
                        break;
677
 
678
                case IP_PORTRANGE:
679
                        if (m == 0 || m->m_len != sizeof(int))
680
                                error = EINVAL;
681
                        else {
682
                                optval = *mtod(m, int *);
683
 
684
                                switch (optval) {
685
 
686
                                case IP_PORTRANGE_DEFAULT:
687
                                        inp->inp_flags &= ~(INP_LOWPORT);
688
                                        inp->inp_flags &= ~(INP_HIGHPORT);
689
                                        break;
690
 
691
                                case IP_PORTRANGE_HIGH:
692
                                        inp->inp_flags &= ~(INP_LOWPORT);
693
                                        inp->inp_flags |= INP_HIGHPORT;
694
                                        break;
695
 
696
                                case IP_PORTRANGE_LOW:
697
                                        inp->inp_flags &= ~(INP_HIGHPORT);
698
                                        inp->inp_flags |= INP_LOWPORT;
699
                                        break;
700
 
701
                                default:
702
                                        error = EINVAL;
703
                                        break;
704
                                }
705
                        }
706
                        break;
707
 
708
                default:
709
                        error = ENOPROTOOPT;
710
                        break;
711
                }
712
                if (m)
713
                        (void)m_free(m);
714
                break;
715
 
716
        case PRCO_GETOPT:
717
                switch (optname) {
718
                case IP_OPTIONS:
719
                case IP_RETOPTS:
720
                        *mp = m = m_get(M_WAIT, MT_SOOPTS);
721
                        if (inp->inp_options) {
722
                                m->m_len = inp->inp_options->m_len;
723
                                bcopy(mtod(inp->inp_options, void *),
724
                                    mtod(m, void *), m->m_len);
725
                        } else
726
                                m->m_len = 0;
727
                        break;
728
 
729
                case IP_TOS:
730
                case IP_TTL:
731
                case IP_RECVOPTS:
732
                case IP_RECVRETOPTS:
733
                case IP_RECVDSTADDR:
734
                case IP_RECVIF:
735
                        *mp = m = m_get(M_WAIT, MT_SOOPTS);
736
                        m->m_len = sizeof(int);
737
                        switch (optname) {
738
 
739
                        case IP_TOS:
740
                                optval = inp->inp_ip_tos;
741
                                break;
742
 
743
                        case IP_TTL:
744
                                optval = inp->inp_ip_ttl;
745
                                break;
746
 
747
#define OPTBIT(bit)     (inp->inp_flags & bit ? 1 : 0)
748
 
749
                        case IP_RECVOPTS:
750
                                optval = OPTBIT(INP_RECVOPTS);
751
                                break;
752
 
753
                        case IP_RECVRETOPTS:
754
                                optval = OPTBIT(INP_RECVRETOPTS);
755
                                break;
756
 
757
                        case IP_RECVDSTADDR:
758
                                optval = OPTBIT(INP_RECVDSTADDR);
759
                                break;
760
 
761
                        case IP_RECVIF:
762
                                optval = OPTBIT(INP_RECVIF);
763
                                break;
764
                        }
765
                        *mtod(m, int *) = optval;
766
                        break;
767
 
768
                case IP_MULTICAST_IF:
769
                case IP_MULTICAST_VIF:
770
                case IP_MULTICAST_TTL:
771
                case IP_MULTICAST_LOOP:
772
                case IP_ADD_MEMBERSHIP:
773
                case IP_DROP_MEMBERSHIP:
774
                        error = ip_getmoptions(optname, inp->inp_moptions, mp);
775
                        break;
776
 
777
                case IP_PORTRANGE:
778
                        *mp = m = m_get(M_WAIT, MT_SOOPTS);
779
                        m->m_len = sizeof(int);
780
 
781
                        if (inp->inp_flags & INP_HIGHPORT)
782
                                optval = IP_PORTRANGE_HIGH;
783
                        else if (inp->inp_flags & INP_LOWPORT)
784
                                optval = IP_PORTRANGE_LOW;
785
                        else
786
                                optval = 0;
787
 
788
                        *mtod(m, int *) = optval;
789
                        break;
790
 
791
                default:
792
                        error = ENOPROTOOPT;
793
                        break;
794
                }
795
                break;
796
        }
797
        return (error);
798
}
799
 
800
/*
801
 * Set up IP options in pcb for insertion in output packets.
802
 * Store in mbuf with pointer in pcbopt, adding pseudo-option
803
 * with destination address if source routed.
804
 */
805
static int
806
#ifdef notyet
807
ip_pcbopts(optname, pcbopt, m)
808
        int optname;
809
#else
810
ip_pcbopts(pcbopt, m)
811
#endif
812
        struct mbuf **pcbopt;
813
        register struct mbuf *m;
814
{
815
        register int cnt, optlen;
816
        register u_char *cp;
817
        u_char opt;
818
 
819
        /* turn off any old options */
820
        if (*pcbopt)
821
                (void)m_free(*pcbopt);
822
        *pcbopt = 0;
823
        if (m == (struct mbuf *)0 || m->m_len == 0) {
824
                /*
825
                 * Only turning off any previous options.
826
                 */
827
                if (m)
828
                        (void)m_free(m);
829
                return (0);
830
        }
831
 
832
#ifndef vax
833
        if (m->m_len % sizeof(long))
834
                goto bad;
835
#endif
836
        /*
837
         * IP first-hop destination address will be stored before
838
         * actual options; move other options back
839
         * and clear it when none present.
840
         */
841
        if (m->m_data + m->m_len + sizeof(struct in_addr) >= &m->m_dat[MLEN])
842
                goto bad;
843
        cnt = m->m_len;
844
        m->m_len += sizeof(struct in_addr);
845
        cp = mtod(m, u_char *) + sizeof(struct in_addr);
846
        ovbcopy(mtod(m, caddr_t), (caddr_t)cp, (unsigned)cnt);
847
        bzero(mtod(m, caddr_t), sizeof(struct in_addr));
848
 
849
        for (; cnt > 0; cnt -= optlen, cp += optlen) {
850
                opt = cp[IPOPT_OPTVAL];
851
                if (opt == IPOPT_EOL)
852
                        break;
853
                if (opt == IPOPT_NOP)
854
                        optlen = 1;
855
                else {
856
                        optlen = cp[IPOPT_OLEN];
857
                        if (optlen <= IPOPT_OLEN || optlen > cnt)
858
                                goto bad;
859
                }
860
                switch (opt) {
861
 
862
                default:
863
                        break;
864
 
865
                case IPOPT_LSRR:
866
                case IPOPT_SSRR:
867
                        /*
868
                         * user process specifies route as:
869
                         *      ->A->B->C->D
870
                         * D must be our final destination (but we can't
871
                         * check that since we may not have connected yet).
872
                         * A is first hop destination, which doesn't appear in
873
                         * actual IP option, but is stored before the options.
874
                         */
875
                        if (optlen < IPOPT_MINOFF - 1 + sizeof(struct in_addr))
876
                                goto bad;
877
                        m->m_len -= sizeof(struct in_addr);
878
                        cnt -= sizeof(struct in_addr);
879
                        optlen -= sizeof(struct in_addr);
880
                        cp[IPOPT_OLEN] = optlen;
881
                        /*
882
                         * Move first hop before start of options.
883
                         */
884
                        bcopy((caddr_t)&cp[IPOPT_OFFSET+1], mtod(m, caddr_t),
885
                            sizeof(struct in_addr));
886
                        /*
887
                         * Then copy rest of options back
888
                         * to close up the deleted entry.
889
                         */
890
                        ovbcopy((caddr_t)(&cp[IPOPT_OFFSET+1] +
891
                            sizeof(struct in_addr)),
892
                            (caddr_t)&cp[IPOPT_OFFSET+1],
893
                            (unsigned)cnt + sizeof(struct in_addr));
894
                        break;
895
                }
896
        }
897
        if (m->m_len > MAX_IPOPTLEN + sizeof(struct in_addr))
898
                goto bad;
899
        *pcbopt = m;
900
        return (0);
901
 
902
bad:
903
        (void)m_free(m);
904
        return (EINVAL);
905
}
906
 
907
/*
908
 * Set the IP multicast options in response to user setsockopt().
909
 */
910
static int
911
ip_setmoptions(optname, imop, m)
912
        int optname;
913
        struct ip_moptions **imop;
914
        struct mbuf *m;
915
{
916
        register int error = 0;
917
        u_char loop;
918
        register int i;
919
        struct in_addr addr;
920
        register struct ip_mreq *mreq;
921
        register struct ifnet *ifp;
922
        register struct ip_moptions *imo = *imop;
923
        struct route ro;
924
        register struct sockaddr_in *dst;
925
        int s;
926
 
927
        if (imo == NULL) {
928
                /*
929
                 * No multicast option buffer attached to the pcb;
930
                 * allocate one and initialize to default values.
931
                 */
932
                imo = (struct ip_moptions*)malloc(sizeof(*imo), M_IPMOPTS,
933
                    M_WAITOK);
934
 
935
                if (imo == NULL)
936
                        return (ENOBUFS);
937
                *imop = imo;
938
                imo->imo_multicast_ifp = NULL;
939
                imo->imo_multicast_vif = -1;
940
                imo->imo_multicast_ttl = IP_DEFAULT_MULTICAST_TTL;
941
                imo->imo_multicast_loop = IP_DEFAULT_MULTICAST_LOOP;
942
                imo->imo_num_memberships = 0;
943
        }
944
 
945
        switch (optname) {
946
        /* store an index number for the vif you wanna use in the send */
947
        case IP_MULTICAST_VIF:
948
                if (!legal_vif_num) {
949
                        error = EOPNOTSUPP;
950
                        break;
951
                }
952
                if (m == NULL || m->m_len != sizeof(int)) {
953
                        error = EINVAL;
954
                        break;
955
                }
956
                i = *(mtod(m, int *));
957
                if (!legal_vif_num(i) && (i != -1)) {
958
                        error = EINVAL;
959
                        break;
960
                }
961
                imo->imo_multicast_vif = i;
962
                break;
963
 
964
        case IP_MULTICAST_IF:
965
                /*
966
                 * Select the interface for outgoing multicast packets.
967
                 */
968
                if (m == NULL || m->m_len != sizeof(struct in_addr)) {
969
                        error = EINVAL;
970
                        break;
971
                }
972
                addr = *(mtod(m, struct in_addr *));
973
                /*
974
                 * INADDR_ANY is used to remove a previous selection.
975
                 * When no interface is selected, a default one is
976
                 * chosen every time a multicast packet is sent.
977
                 */
978
                if (addr.s_addr == INADDR_ANY) {
979
                        imo->imo_multicast_ifp = NULL;
980
                        break;
981
                }
982
                /*
983
                 * The selected interface is identified by its local
984
                 * IP address.  Find the interface and confirm that
985
                 * it supports multicasting.
986
                 */
987
                s = splimp();
988
                INADDR_TO_IFP(addr, ifp);
989
                if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0) {
990
                        splx(s);
991
                        error = EADDRNOTAVAIL;
992
                        break;
993
                }
994
                imo->imo_multicast_ifp = ifp;
995
                splx(s);
996
                break;
997
 
998
        case IP_MULTICAST_TTL:
999
                /*
1000
                 * Set the IP time-to-live for outgoing multicast packets.
1001
                 */
1002
                if (m == NULL || m->m_len != 1) {
1003
                        error = EINVAL;
1004
                        break;
1005
                }
1006
                imo->imo_multicast_ttl = *(mtod(m, u_char *));
1007
                break;
1008
 
1009
        case IP_MULTICAST_LOOP:
1010
                /*
1011
                 * Set the loopback flag for outgoing multicast packets.
1012
                 * Must be zero or one.
1013
                 */
1014
                if (m == NULL || m->m_len != 1 ||
1015
                   (loop = *(mtod(m, u_char *))) > 1) {
1016
                        error = EINVAL;
1017
                        break;
1018
                }
1019
                imo->imo_multicast_loop = loop;
1020
                break;
1021
 
1022
        case IP_ADD_MEMBERSHIP:
1023
                /*
1024
                 * Add a multicast group membership.
1025
                 * Group must be a valid IP multicast address.
1026
                 */
1027
                if (m == NULL || m->m_len != sizeof(struct ip_mreq)) {
1028
                        error = EINVAL;
1029
                        break;
1030
                }
1031
                mreq = mtod(m, struct ip_mreq *);
1032
                if (!IN_MULTICAST(ntohl(mreq->imr_multiaddr.s_addr))) {
1033
                        error = EINVAL;
1034
                        break;
1035
                }
1036
                s = splimp();
1037
                /*
1038
                 * If no interface address was provided, use the interface of
1039
                 * the route to the given multicast address.
1040
                 */
1041
                if (mreq->imr_interface.s_addr == INADDR_ANY) {
1042
                        bzero((caddr_t)&ro, sizeof(ro));
1043
                        dst = (struct sockaddr_in *)&ro.ro_dst;
1044
                        dst->sin_len = sizeof(*dst);
1045
                        dst->sin_family = AF_INET;
1046
                        dst->sin_addr = mreq->imr_multiaddr;
1047
                        rtalloc(&ro);
1048
                        if (ro.ro_rt == NULL) {
1049
                                error = EADDRNOTAVAIL;
1050
                                splx(s);
1051
                                break;
1052
                        }
1053
                        ifp = ro.ro_rt->rt_ifp;
1054
                        rtfree(ro.ro_rt);
1055
                }
1056
                else {
1057
                        INADDR_TO_IFP(mreq->imr_interface, ifp);
1058
                }
1059
 
1060
                /*
1061
                 * See if we found an interface, and confirm that it
1062
                 * supports multicast.
1063
                 */
1064
                if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0) {
1065
                        error = EADDRNOTAVAIL;
1066
                        splx(s);
1067
                        break;
1068
                }
1069
                /*
1070
                 * See if the membership already exists or if all the
1071
                 * membership slots are full.
1072
                 */
1073
                for (i = 0; i < imo->imo_num_memberships; ++i) {
1074
                        if (imo->imo_membership[i]->inm_ifp == ifp &&
1075
                            imo->imo_membership[i]->inm_addr.s_addr
1076
                                                == mreq->imr_multiaddr.s_addr)
1077
                                break;
1078
                }
1079
                if (i < imo->imo_num_memberships) {
1080
                        error = EADDRINUSE;
1081
                        splx(s);
1082
                        break;
1083
                }
1084
                if (i == IP_MAX_MEMBERSHIPS) {
1085
                        error = ETOOMANYREFS;
1086
                        splx(s);
1087
                        break;
1088
                }
1089
                /*
1090
                 * Everything looks good; add a new record to the multicast
1091
                 * address list for the given interface.
1092
                 */
1093
                if ((imo->imo_membership[i] =
1094
                    in_addmulti(&mreq->imr_multiaddr, ifp)) == NULL) {
1095
                        error = ENOBUFS;
1096
                        splx(s);
1097
                        break;
1098
                }
1099
                ++imo->imo_num_memberships;
1100
                splx(s);
1101
                break;
1102
 
1103
        case IP_DROP_MEMBERSHIP:
1104
                /*
1105
                 * Drop a multicast group membership.
1106
                 * Group must be a valid IP multicast address.
1107
                 */
1108
                if (m == NULL || m->m_len != sizeof(struct ip_mreq)) {
1109
                        error = EINVAL;
1110
                        break;
1111
                }
1112
                mreq = mtod(m, struct ip_mreq *);
1113
                if (!IN_MULTICAST(ntohl(mreq->imr_multiaddr.s_addr))) {
1114
                        error = EINVAL;
1115
                        break;
1116
                }
1117
 
1118
                s = splimp();
1119
                /*
1120
                 * If an interface address was specified, get a pointer
1121
                 * to its ifnet structure.
1122
                 */
1123
                if (mreq->imr_interface.s_addr == INADDR_ANY)
1124
                        ifp = NULL;
1125
                else {
1126
                        INADDR_TO_IFP(mreq->imr_interface, ifp);
1127
                        if (ifp == NULL) {
1128
                                error = EADDRNOTAVAIL;
1129
                                splx(s);
1130
                                break;
1131
                        }
1132
                }
1133
                /*
1134
                 * Find the membership in the membership array.
1135
                 */
1136
                for (i = 0; i < imo->imo_num_memberships; ++i) {
1137
                        if ((ifp == NULL ||
1138
                             imo->imo_membership[i]->inm_ifp == ifp) &&
1139
                             imo->imo_membership[i]->inm_addr.s_addr ==
1140
                             mreq->imr_multiaddr.s_addr)
1141
                                break;
1142
                }
1143
                if (i == imo->imo_num_memberships) {
1144
                        error = EADDRNOTAVAIL;
1145
                        splx(s);
1146
                        break;
1147
                }
1148
                /*
1149
                 * Give up the multicast address record to which the
1150
                 * membership points.
1151
                 */
1152
                in_delmulti(imo->imo_membership[i]);
1153
                /*
1154
                 * Remove the gap in the membership array.
1155
                 */
1156
                for (++i; i < imo->imo_num_memberships; ++i)
1157
                        imo->imo_membership[i-1] = imo->imo_membership[i];
1158
                --imo->imo_num_memberships;
1159
                splx(s);
1160
                break;
1161
 
1162
        default:
1163
                error = EOPNOTSUPP;
1164
                break;
1165
        }
1166
 
1167
        /*
1168
         * If all options have default values, no need to keep the mbuf.
1169
         */
1170
        if (imo->imo_multicast_ifp == NULL &&
1171
            imo->imo_multicast_vif == -1 &&
1172
            imo->imo_multicast_ttl == IP_DEFAULT_MULTICAST_TTL &&
1173
            imo->imo_multicast_loop == IP_DEFAULT_MULTICAST_LOOP &&
1174
            imo->imo_num_memberships == 0) {
1175
                free(*imop, M_IPMOPTS);
1176
                *imop = NULL;
1177
        }
1178
 
1179
        return (error);
1180
}
1181
 
1182
/*
1183
 * Return the IP multicast options in response to user getsockopt().
1184
 */
1185
static int
1186
ip_getmoptions(optname, imo, mp)
1187
        int optname;
1188
        register struct ip_moptions *imo;
1189
        register struct mbuf **mp;
1190
{
1191
        u_char *ttl;
1192
        u_char *loop;
1193
        struct in_addr *addr;
1194
        struct in_ifaddr *ia;
1195
 
1196
        *mp = m_get(M_WAIT, MT_SOOPTS);
1197
 
1198
        switch (optname) {
1199
 
1200
        case IP_MULTICAST_VIF:
1201
                if (imo != NULL)
1202
                        *(mtod(*mp, int *)) = imo->imo_multicast_vif;
1203
                else
1204
                        *(mtod(*mp, int *)) = -1;
1205
                (*mp)->m_len = sizeof(int);
1206
                return(0);
1207
 
1208
        case IP_MULTICAST_IF:
1209
                addr = mtod(*mp, struct in_addr *);
1210
                (*mp)->m_len = sizeof(struct in_addr);
1211
                if (imo == NULL || imo->imo_multicast_ifp == NULL)
1212
                        addr->s_addr = INADDR_ANY;
1213
                else {
1214
                        IFP_TO_IA(imo->imo_multicast_ifp, ia);
1215
                        addr->s_addr = (ia == NULL) ? INADDR_ANY
1216
                                        : IA_SIN(ia)->sin_addr.s_addr;
1217
                }
1218
                return (0);
1219
 
1220
        case IP_MULTICAST_TTL:
1221
                ttl = mtod(*mp, u_char *);
1222
                (*mp)->m_len = 1;
1223
                *ttl = (imo == NULL) ? IP_DEFAULT_MULTICAST_TTL
1224
                                     : imo->imo_multicast_ttl;
1225
                return (0);
1226
 
1227
        case IP_MULTICAST_LOOP:
1228
                loop = mtod(*mp, u_char *);
1229
                (*mp)->m_len = 1;
1230
                *loop = (imo == NULL) ? IP_DEFAULT_MULTICAST_LOOP
1231
                                      : imo->imo_multicast_loop;
1232
                return (0);
1233
 
1234
        default:
1235
                return (EOPNOTSUPP);
1236
        }
1237
}
1238
 
1239
/*
1240
 * Discard the IP multicast options.
1241
 */
1242
void
1243
ip_freemoptions(imo)
1244
        register struct ip_moptions *imo;
1245
{
1246
        register int i;
1247
 
1248
        if (imo != NULL) {
1249
                for (i = 0; i < imo->imo_num_memberships; ++i)
1250
                        in_delmulti(imo->imo_membership[i]);
1251
                free(imo, M_IPMOPTS);
1252
        }
1253
}
1254
 
1255
/*
1256
 * Routine called from ip_output() to loop back a copy of an IP multicast
1257
 * packet to the input queue of a specified interface.  Note that this
1258
 * calls the output routine of the loopback "driver", but with an interface
1259
 * pointer that might NOT be a loopback interface -- evil, but easier than
1260
 * replicating that code here.
1261
 */
1262
static void
1263
ip_mloopback(ifp, m, dst, hlen)
1264
        struct ifnet *ifp;
1265
        register struct mbuf *m;
1266
        register struct sockaddr_in *dst;
1267
        int hlen;
1268
{
1269
        register struct ip *ip;
1270
        struct mbuf *copym;
1271
 
1272
        copym = m_copy(m, 0, M_COPYALL);
1273
        if (copym != NULL && (copym->m_flags & M_EXT || copym->m_len < hlen))
1274
                copym = m_pullup(copym, hlen);
1275
        if (copym != NULL) {
1276
                /*
1277
                 * We don't bother to fragment if the IP length is greater
1278
                 * than the interface's MTU.  Can this possibly matter?
1279
                 */
1280
                ip = mtod(copym, struct ip *);
1281
                ip->ip_len = htons((u_short)ip->ip_len);
1282
                ip->ip_off = htons((u_short)ip->ip_off);
1283
                ip->ip_sum = 0;
1284
                if (ip->ip_vhl == IP_VHL_BORING) {
1285
                        ip->ip_sum = in_cksum_hdr(ip);
1286
                } else {
1287
                        ip->ip_sum = in_cksum(copym, hlen);
1288
                }
1289
                /*
1290
                 * NB:
1291
                 * It's not clear whether there are any lingering
1292
                 * reentrancy problems in other areas which might
1293
                 * be exposed by using ip_input directly (in
1294
                 * particular, everything which modifies the packet
1295
                 * in-place).  Yet another option is using the
1296
                 * protosw directly to deliver the looped back
1297
                 * packet.  For the moment, we'll err on the side
1298
                 * of safety by continuing to abuse looutput().
1299
                 */
1300
#ifdef notdef
1301
                copym->m_pkthdr.rcvif = ifp;
1302
                ip_input(copym)
1303
#else
1304
                (void) looutput(ifp, copym, (struct sockaddr *)dst, NULL);
1305
#endif
1306
        }
1307
}

powered by: WebSVN 2.1.0

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