The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netinet/ip_output.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    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  * $FreeBSD$
   35  */
   36 
   37 #define _IP_VHL
   38 
   39 #include "opt_ipfw.h"
   40 #include "opt_ipdn.h"
   41 #include "opt_ipdivert.h"
   42 #include "opt_ipfilter.h"
   43 
   44 #include <sys/param.h>
   45 #include <sys/systm.h>
   46 #include <sys/kernel.h>
   47 #include <sys/malloc.h>
   48 #include <sys/mbuf.h>
   49 #include <sys/protosw.h>
   50 #include <sys/socket.h>
   51 #include <sys/socketvar.h>
   52 
   53 #include <net/if.h>
   54 #include <net/route.h>
   55 
   56 #include <netinet/in.h>
   57 #include <netinet/in_systm.h>
   58 #include <netinet/ip.h>
   59 #include <netinet/in_pcb.h>
   60 #include <netinet/in_var.h>
   61 #include <netinet/ip_var.h>
   62 
   63 #ifdef vax
   64 #include <machine/mtpr.h>
   65 #endif
   66 #include <machine/in_cksum.h>
   67 
   68 static MALLOC_DEFINE(M_IPMOPTS, "ip_moptions", "internet multicast options");
   69 
   70 #if !defined(COMPAT_IPFW) || COMPAT_IPFW == 1
   71 #undef COMPAT_IPFW
   72 #define COMPAT_IPFW 1
   73 #else
   74 #undef COMPAT_IPFW
   75 #endif
   76 
   77 #ifdef COMPAT_IPFW
   78 #include <netinet/ip_fw.h>
   79 #endif
   80 
   81 #ifdef DUMMYNET
   82 #include <netinet/ip_dummynet.h>
   83 #endif
   84 
   85 #ifdef IPFIREWALL_FORWARD_DEBUG
   86 #define print_ip(a)      printf("%ld.%ld.%ld.%ld",(ntohl(a.s_addr)>>24)&0xFF,\
   87                                                   (ntohl(a.s_addr)>>16)&0xFF,\
   88                                                   (ntohl(a.s_addr)>>8)&0xFF,\
   89                                                   (ntohl(a.s_addr))&0xFF);
   90 #endif
   91 
   92 u_short ip_id;
   93 
   94 static struct mbuf *ip_insertoptions __P((struct mbuf *, struct mbuf *, int *));
   95 static void     ip_mloopback
   96         __P((struct ifnet *, struct mbuf *, struct sockaddr_in *, int));
   97 static int      ip_getmoptions
   98         __P((struct sockopt *, struct ip_moptions *));
   99 static int      ip_pcbopts __P((int, struct mbuf **, struct mbuf *));
  100 static int      ip_setmoptions
  101         __P((struct sockopt *, struct ip_moptions **));
  102 
  103 #if defined(IPFILTER_LKM) || defined(IPFILTER)
  104 int     ip_optcopy __P((struct ip *, struct ip *));
  105 extern int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **));
  106 #else
  107 static int      ip_optcopy __P((struct ip *, struct ip *));
  108 #endif
  109 
  110 
  111 extern  struct protosw inetsw[];
  112 
  113 /*
  114  * IP output.  The packet in mbuf chain m contains a skeletal IP
  115  * header (with len, off, ttl, proto, tos, src, dst).
  116  * The mbuf chain containing the packet will be freed.
  117  * The mbuf opt, if present, will not be freed.
  118  */
  119 int
  120 ip_output(m0, opt, ro, flags, imo)
  121         struct mbuf *m0;
  122         struct mbuf *opt;
  123         struct route *ro;
  124         int flags;
  125         struct ip_moptions *imo;
  126 {
  127         struct ip *ip, *mhip;
  128         struct ifnet *ifp;
  129         struct mbuf *m = m0;
  130         int hlen = sizeof (struct ip);
  131         int len, off, error = 0;
  132         struct sockaddr_in *dst;
  133         struct in_ifaddr *ia;
  134         int isbroadcast;
  135 #ifdef IPFIREWALL_FORWARD
  136         int fwd_rewrite_src = 0;
  137 #endif
  138 
  139 #ifndef IPDIVERT /* dummy variable for the firewall code to play with */
  140         u_short ip_divert_cookie = 0 ;
  141 #endif
  142 #ifdef COMPAT_IPFW
  143         struct ip_fw_chain *rule = NULL ;
  144 #endif
  145 
  146 #if defined(IPFIREWALL) && defined(DUMMYNET)
  147         /*  
  148          * dummynet packet are prepended a vestigial mbuf with
  149          * m_type = MT_DUMMYNET and m_data pointing to the matching
  150          * rule.
  151          */ 
  152         if (m->m_type == MT_DUMMYNET) {
  153             /*
  154              * the packet was already tagged, so part of the
  155              * processing was already done, and we need to go down.
  156              * Get parameters from the header.
  157              */
  158             rule = (struct ip_fw_chain *)(m->m_data) ;
  159             opt = NULL ;
  160             ro = & ( ((struct dn_pkt *)m)->ro ) ;
  161             flags = 0 ; /* XXX is this correct ? */
  162             imo = NULL ;
  163             dst = ((struct dn_pkt *)m)->dn_dst ;
  164             ifp = ((struct dn_pkt *)m)->ifp ;
  165 
  166             m0 = m = m->m_next ;
  167             ip = mtod(m, struct ip *);
  168             hlen = IP_VHL_HL(ip->ip_vhl) << 2 ;
  169             goto sendit;
  170         } else
  171             rule = NULL ;
  172 #endif
  173 
  174 #ifdef  DIAGNOSTIC
  175         if ((m->m_flags & M_PKTHDR) == 0)
  176                 panic("ip_output no HDR");
  177         if (!ro)
  178                 panic("ip_output no route, proto = %d",
  179                       mtod(m, struct ip *)->ip_p);
  180 #endif
  181         if (opt) {
  182                 m = ip_insertoptions(m, opt, &len);
  183                 hlen = len;
  184         }
  185         ip = mtod(m, struct ip *);
  186         /*
  187          * Fill in IP header.
  188          */
  189         if ((flags & (IP_FORWARDING|IP_RAWOUTPUT)) == 0) {
  190                 ip->ip_vhl = IP_MAKE_VHL(IPVERSION, hlen >> 2);
  191                 ip->ip_off &= IP_DF;
  192                 ip->ip_id = htons(ip_id++);
  193                 ipstat.ips_localout++;
  194         } else {
  195                 hlen = IP_VHL_HL(ip->ip_vhl) << 2;
  196         }
  197 
  198         dst = (struct sockaddr_in *)&ro->ro_dst;
  199         /*
  200          * If there is a cached route,
  201          * check that it is to the same destination
  202          * and is still up.  If not, free it and try again.
  203          */
  204         if (ro->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 ||
  205            dst->sin_addr.s_addr != ip->ip_dst.s_addr)) {
  206                 RTFREE(ro->ro_rt);
  207                 ro->ro_rt = (struct rtentry *)0;
  208         }
  209         if (ro->ro_rt == 0) {
  210                 dst->sin_family = AF_INET;
  211                 dst->sin_len = sizeof(*dst);
  212                 dst->sin_addr = ip->ip_dst;
  213         }
  214         /*
  215          * If routing to interface only,
  216          * short circuit routing lookup.
  217          */
  218 #define ifatoia(ifa)    ((struct in_ifaddr *)(ifa))
  219 #define sintosa(sin)    ((struct sockaddr *)(sin))
  220         if (flags & IP_ROUTETOIF) {
  221                 if ((ia = ifatoia(ifa_ifwithdstaddr(sintosa(dst)))) == 0 &&
  222                     (ia = ifatoia(ifa_ifwithnet(sintosa(dst)))) == 0) {
  223                         ipstat.ips_noroute++;
  224                         error = ENETUNREACH;
  225                         goto bad;
  226                 }
  227                 ifp = ia->ia_ifp;
  228                 ip->ip_ttl = 1;
  229                 isbroadcast = in_broadcast(dst->sin_addr, ifp);
  230         } else {
  231                 /*
  232                  * If this is the case, we probably don't want to allocate
  233                  * a protocol-cloned route since we didn't get one from the
  234                  * ULP.  This lets TCP do its thing, while not burdening
  235                  * forwarding or ICMP with the overhead of cloning a route.
  236                  * Of course, we still want to do any cloning requested by
  237                  * the link layer, as this is probably required in all cases
  238                  * for correct operation (as it is for ARP).
  239                  */
  240                 if (ro->ro_rt == 0)
  241                         rtalloc_ign(ro, RTF_PRCLONING);
  242                 if (ro->ro_rt == 0) {
  243                         ipstat.ips_noroute++;
  244                         error = EHOSTUNREACH;
  245                         goto bad;
  246                 }
  247                 ia = ifatoia(ro->ro_rt->rt_ifa);
  248                 ifp = ro->ro_rt->rt_ifp;
  249                 ro->ro_rt->rt_use++;
  250                 if (ro->ro_rt->rt_flags & RTF_GATEWAY)
  251                         dst = (struct sockaddr_in *)ro->ro_rt->rt_gateway;
  252                 if (ro->ro_rt->rt_flags & RTF_HOST)
  253                         isbroadcast = (ro->ro_rt->rt_flags & RTF_BROADCAST);
  254                 else
  255                         isbroadcast = in_broadcast(dst->sin_addr, ifp);
  256         }
  257         if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) {
  258                 struct in_multi *inm;
  259 
  260                 m->m_flags |= M_MCAST;
  261                 /*
  262                  * IP destination address is multicast.  Make sure "dst"
  263                  * still points to the address in "ro".  (It may have been
  264                  * changed to point to a gateway address, above.)
  265                  */
  266                 dst = (struct sockaddr_in *)&ro->ro_dst;
  267                 /*
  268                  * See if the caller provided any multicast options
  269                  */
  270                 if (imo != NULL) {
  271                         ip->ip_ttl = imo->imo_multicast_ttl;
  272                         if (imo->imo_multicast_ifp != NULL)
  273                                 ifp = imo->imo_multicast_ifp;
  274                         if (imo->imo_multicast_vif != -1)
  275                                 ip->ip_src.s_addr =
  276                                     ip_mcast_src(imo->imo_multicast_vif);
  277                 } else
  278                         ip->ip_ttl = IP_DEFAULT_MULTICAST_TTL;
  279                 /*
  280                  * Confirm that the outgoing interface supports multicast.
  281                  */
  282                 if ((imo == NULL) || (imo->imo_multicast_vif == -1)) {
  283                         if ((ifp->if_flags & IFF_MULTICAST) == 0) {
  284                                 ipstat.ips_noroute++;
  285                                 error = ENETUNREACH;
  286                                 goto bad;
  287                         }
  288                 }
  289                 /*
  290                  * If source address not specified yet, use address
  291                  * of outgoing interface.
  292                  */
  293                 if (ip->ip_src.s_addr == INADDR_ANY) {
  294                         register struct in_ifaddr *ia1;
  295 
  296                         for (ia1 = in_ifaddrhead.tqh_first; ia1;
  297                              ia1 = ia1->ia_link.tqe_next)
  298                                 if (ia1->ia_ifp == ifp) {
  299                                         ip->ip_src = IA_SIN(ia1)->sin_addr;
  300                                         break;
  301                                 }
  302                 }
  303 
  304                 IN_LOOKUP_MULTI(ip->ip_dst, ifp, inm);
  305                 if (inm != NULL &&
  306                    (imo == NULL || imo->imo_multicast_loop)) {
  307                         /*
  308                          * If we belong to the destination multicast group
  309                          * on the outgoing interface, and the caller did not
  310                          * forbid loopback, loop back a copy.
  311                          */
  312                         ip_mloopback(ifp, m, dst, hlen);
  313                 }
  314                 else {
  315                         /*
  316                          * If we are acting as a multicast router, perform
  317                          * multicast forwarding as if the packet had just
  318                          * arrived on the interface to which we are about
  319                          * to send.  The multicast forwarding function
  320                          * recursively calls this function, using the
  321                          * IP_FORWARDING flag to prevent infinite recursion.
  322                          *
  323                          * Multicasts that are looped back by ip_mloopback(),
  324                          * above, will be forwarded by the ip_input() routine,
  325                          * if necessary.
  326                          */
  327                         if (ip_mrouter && (flags & IP_FORWARDING) == 0) {
  328                                 /*
  329                                  * Check if rsvp daemon is running. If not, don't
  330                                  * set ip_moptions. This ensures that the packet
  331                                  * is multicast and not just sent down one link
  332                                  * as prescribed by rsvpd.
  333                                  */
  334                                 if (!rsvp_on)
  335                                   imo = NULL;
  336                                 if (ip_mforward(ip, ifp, m, imo) != 0) {
  337                                         m_freem(m);
  338                                         goto done;
  339                                 }
  340                         }
  341                 }
  342 
  343                 /*
  344                  * Multicasts with a time-to-live of zero may be looped-
  345                  * back, above, but must not be transmitted on a network.
  346                  * Also, multicasts addressed to the loopback interface
  347                  * are not sent -- the above call to ip_mloopback() will
  348                  * loop back a copy if this host actually belongs to the
  349                  * destination group on the loopback interface.
  350                  */
  351                 if (ip->ip_ttl == 0 || ifp->if_flags & IFF_LOOPBACK) {
  352                         m_freem(m);
  353                         goto done;
  354                 }
  355 
  356                 goto sendit;
  357         }
  358 #ifndef notdef
  359         /*
  360          * If source address not specified yet, use address
  361          * of outgoing interface.
  362          */
  363         if (ip->ip_src.s_addr == INADDR_ANY) {
  364                 ip->ip_src = IA_SIN(ia)->sin_addr;
  365 #ifdef IPFIREWALL_FORWARD
  366                 /* Keep note that we did this - if the firewall changes
  367                  * the next-hop, our interface may change, changing the
  368                  * default source IP. It's a shame so much effort happens
  369                  * twice. Oh well. 
  370                  */
  371                 fwd_rewrite_src++;
  372 #endif /* IPFIREWALL_FORWARD */
  373         }
  374 #endif /* notdef */
  375         /*
  376          * Verify that we have any chance at all of being able to queue
  377          *      the packet or packet fragments
  378          */
  379         if ((ifp->if_snd.ifq_len + ip->ip_len / ifp->if_mtu + 1) >=
  380                 ifp->if_snd.ifq_maxlen) {
  381                         error = ENOBUFS;
  382                         goto bad;
  383         }
  384 
  385         /*
  386          * Look for broadcast address and
  387          * and verify user is allowed to send
  388          * such a packet.
  389          */
  390         if (isbroadcast) {
  391                 if ((ifp->if_flags & IFF_BROADCAST) == 0) {
  392                         error = EADDRNOTAVAIL;
  393                         goto bad;
  394                 }
  395                 if ((flags & IP_ALLOWBROADCAST) == 0) {
  396                         error = EACCES;
  397                         goto bad;
  398                 }
  399                 /* don't allow broadcast messages to be fragmented */
  400                 if ((u_short)ip->ip_len > ifp->if_mtu) {
  401                         error = EMSGSIZE;
  402                         goto bad;
  403                 }
  404                 m->m_flags |= M_BCAST;
  405         } else {
  406                 m->m_flags &= ~M_BCAST;
  407         }
  408 
  409 sendit:
  410         /*
  411          * IpHack's section.
  412          * - Xlate: translate packet's addr/port (NAT).
  413          * - Firewall: deny/allow/etc.
  414          * - Wrap: fake packet's addr/port <unimpl.>
  415          * - Encapsulate: put it in another IP and send out. <unimp.>
  416          */ 
  417 #if defined(IPFILTER) || defined(IPFILTER_LKM)
  418         if (fr_checkp) {
  419                 struct  mbuf    *m1 = m;
  420 
  421                 if ((error = (*fr_checkp)(ip, hlen, ifp, 1, &m1)) || !m1)
  422                         goto done;
  423                 ip = mtod(m = m1, struct ip *);
  424         }
  425 #endif
  426 
  427 #ifdef COMPAT_IPFW
  428         /*
  429          * Check with the firewall...
  430          */
  431         if (fw_enable && ip_fw_chk_ptr) {
  432                 struct sockaddr_in *old = dst;
  433 
  434                 off = (*ip_fw_chk_ptr)(&ip,
  435                     hlen, ifp, &ip_divert_cookie, &m, &rule, &dst);
  436                 /*
  437                  * On return we must do the following:
  438                  * m == NULL         -> drop the pkt
  439                  * 1<=off<= 0xffff   -> DIVERT
  440                  * (off & 0x10000)   -> send to a DUMMYNET pipe
  441                  * dst != old        -> IPFIREWALL_FORWARD
  442                  * off==0, dst==old  -> accept
  443                  * If some of the above modules is not compiled in, then
  444                  * we should't have to check the corresponding condition
  445                  * (because the ipfw control socket should not accept
  446                  * unsupported rules), but better play safe and drop
  447                  * packets in case of doubt.
  448                  */
  449                 if (!m) { /* firewall said to reject */
  450                         error = EACCES;
  451                         goto done;
  452                 }
  453                 if (off == 0 && dst == old) /* common case */
  454                         goto pass ;
  455 #ifdef DUMMYNET
  456                 if (off & 0x10000) {  
  457                     /*
  458                      * pass the pkt to dummynet. Need to include
  459                      * pipe number, m, ifp, ro, dst because these are
  460                      * not recomputed in the next pass.
  461                      * All other parameters have been already used and
  462                      * so they are not needed anymore. 
  463                      * XXX note: if the ifp or ro entry are deleted
  464                      * while a pkt is in dummynet, we are in trouble!
  465                      */ 
  466                     dummynet_io(off & 0xffff, DN_TO_IP_OUT, m,ifp,ro,dst,rule);
  467                         goto done;
  468                 }
  469 #endif   
  470 #ifdef IPDIVERT
  471                 if (off > 0 && off < 0x10000) {         /* Divert packet */
  472                        ip_divert_port = off & 0xffff ;
  473                        (*inetsw[ip_protox[IPPROTO_DIVERT]].pr_input)(m, 0);
  474                         goto done;
  475                 }
  476 #endif
  477 
  478 #ifdef IPFIREWALL_FORWARD
  479                 /* Here we check dst to make sure it's directly reachable on the
  480                  * interface we previously thought it was.
  481                  * If it isn't (which may be likely in some situations) we have
  482                  * to re-route it (ie, find a route for the next-hop and the
  483                  * associated interface) and set them here. This is nested
  484                  * forwarding which in most cases is undesirable, except where
  485                  * such control is nigh impossible. So we do it here.
  486                  * And I'm babbling.
  487                  */
  488                 if (off == 0 && old != dst) {
  489                         struct in_ifaddr *ia;
  490 
  491                         /* It's changed... */
  492                         /* There must be a better way to do this next line... */
  493                         static struct route sro_fwd, *ro_fwd = &sro_fwd;
  494 #ifdef IPFIREWALL_FORWARD_DEBUG
  495                         printf("IPFIREWALL_FORWARD: New dst ip: ");
  496                         print_ip(dst->sin_addr);
  497                         printf("\n");
  498 #endif
  499                         /*
  500                          * We need to figure out if we have been forwarded
  501                          * to a local socket. If so then we should somehow 
  502                          * "loop back" to ip_input, and get directed to the
  503                          * PCB as if we had received this packet. This is
  504                          * because it may be dificult to identify the packets
  505                          * you want to forward until they are being output
  506                          * and have selected an interface. (e.g. locally
  507                          * initiated packets) If we used the loopback inteface,
  508                          * we would not be able to control what happens 
  509                          * as the packet runs through ip_input() as
  510                          * it is done through a ISR.
  511                          */
  512                         for (ia = TAILQ_FIRST(&in_ifaddrhead); ia;
  513                                         ia = TAILQ_NEXT(ia, ia_link)) {
  514                                 /*
  515                                  * If the addr to forward to is one
  516                                  * of ours, we pretend to
  517                                  * be the destination for this packet.
  518                                  */
  519                                 if (IA_SIN(ia)->sin_addr.s_addr ==
  520                                                  dst->sin_addr.s_addr)
  521                                         break;
  522                         }
  523                         if (ia) {
  524                                 /* tell ip_input "dont filter" */
  525                                 ip_fw_fwd_addr = dst;
  526                                 if (m->m_pkthdr.rcvif == NULL)
  527                                         m->m_pkthdr.rcvif = ifunit("lo0");
  528                                 ip->ip_len = htons((u_short)ip->ip_len);
  529                                 ip->ip_off = htons((u_short)ip->ip_off);
  530                                 ip->ip_sum = 0;
  531                                 if (ip->ip_vhl == IP_VHL_BORING) {
  532                                         ip->ip_sum = in_cksum_hdr(ip);
  533                                 } else {
  534                                         ip->ip_sum = in_cksum(m, hlen);
  535                                 }
  536                                 ip_input(m);
  537                                 goto done;
  538                         }
  539                         /* Some of the logic for this was
  540                          * nicked from above.
  541                          *
  542                          * This rewrites the cached route in a local PCB.
  543                          * Is this what we want to do?
  544                          */
  545                         bcopy(dst, &ro_fwd->ro_dst, sizeof(*dst));
  546 
  547                         ro_fwd->ro_rt = 0;
  548                         rtalloc_ign(ro_fwd, RTF_PRCLONING);
  549 
  550                         if (ro_fwd->ro_rt == 0) {
  551                                 ipstat.ips_noroute++;
  552                                 error = EHOSTUNREACH;
  553                                 goto bad;
  554                         }
  555 
  556                         ia = ifatoia(ro_fwd->ro_rt->rt_ifa);
  557                         ifp = ro_fwd->ro_rt->rt_ifp;
  558                         ro_fwd->ro_rt->rt_use++;
  559                         if (ro_fwd->ro_rt->rt_flags & RTF_GATEWAY)
  560                                 dst = (struct sockaddr_in *)ro_fwd->ro_rt->rt_gateway;
  561                         if (ro_fwd->ro_rt->rt_flags & RTF_HOST)
  562                                 isbroadcast =
  563                                     (ro_fwd->ro_rt->rt_flags & RTF_BROADCAST);
  564                         else
  565                                 isbroadcast = in_broadcast(dst->sin_addr, ifp);
  566                         RTFREE(ro->ro_rt);
  567                         ro->ro_rt = ro_fwd->ro_rt;
  568                         dst = (struct sockaddr_in *)&ro_fwd->ro_dst;
  569 
  570                         /*
  571                          * If we added a default src ip earlier,
  572                          * which would have been gotten from the-then
  573                          * interface, do it again, from the new one.
  574                          */
  575                         if (fwd_rewrite_src)
  576                                 ip->ip_src = IA_SIN(ia)->sin_addr;
  577                         goto pass ;
  578                 }
  579 #endif /* IPFIREWALL_FORWARD */
  580                 /*
  581                  * if we get here, none of the above matches, and 
  582                  * we have to drop the pkt
  583                  */
  584                 m_freem(m);
  585                 error = EACCES; /* not sure this is the right error msg */
  586                 goto done;
  587         }
  588 #endif /* COMPAT_IPFW */
  589 
  590 pass:
  591         /*
  592          * If small enough for interface, can just send directly.
  593          */
  594         if ((u_short)ip->ip_len <= ifp->if_mtu) {
  595                 ip->ip_len = htons((u_short)ip->ip_len);
  596                 ip->ip_off = htons((u_short)ip->ip_off);
  597                 ip->ip_sum = 0;
  598                 if (ip->ip_vhl == IP_VHL_BORING) {
  599                         ip->ip_sum = in_cksum_hdr(ip);
  600                 } else {
  601                         ip->ip_sum = in_cksum(m, hlen);
  602                 }
  603                 error = (*ifp->if_output)(ifp, m,
  604                                 (struct sockaddr *)dst, ro->ro_rt);
  605                 goto done;
  606         }
  607         /*
  608          * Too large for interface; fragment if possible.
  609          * Must be able to put at least 8 bytes per fragment.
  610          */
  611         if (ip->ip_off & IP_DF) {
  612                 error = EMSGSIZE;
  613                 /*
  614                  * This case can happen if the user changed the MTU
  615                  * of an interface after enabling IP on it.  Because
  616                  * most netifs don't keep track of routes pointing to
  617                  * them, there is no way for one to update all its
  618                  * routes when the MTU is changed.
  619                  */
  620                 if ((ro->ro_rt->rt_flags & (RTF_UP | RTF_HOST))
  621                     && !(ro->ro_rt->rt_rmx.rmx_locks & RTV_MTU)
  622                     && (ro->ro_rt->rt_rmx.rmx_mtu > ifp->if_mtu)) {
  623                         ro->ro_rt->rt_rmx.rmx_mtu = ifp->if_mtu;
  624                 }
  625                 ipstat.ips_cantfrag++;
  626                 goto bad;
  627         }
  628         len = (ifp->if_mtu - hlen) &~ 7;
  629         if (len < 8) {
  630                 error = EMSGSIZE;
  631                 goto bad;
  632         }
  633 
  634     {
  635         int mhlen, firstlen = len;
  636         struct mbuf **mnext = &m->m_nextpkt;
  637 
  638         /*
  639          * Loop through length of segment after first fragment,
  640          * make new header and copy data of each part and link onto chain.
  641          */
  642         m0 = m;
  643         mhlen = sizeof (struct ip);
  644         for (off = hlen + len; off < (u_short)ip->ip_len; off += len) {
  645                 MGETHDR(m, M_DONTWAIT, MT_HEADER);
  646                 if (m == 0) {
  647                         error = ENOBUFS;
  648                         ipstat.ips_odropped++;
  649                         goto sendorfree;
  650                 }
  651                 m->m_flags |= (m0->m_flags & M_MCAST);
  652                 m->m_data += max_linkhdr;
  653                 mhip = mtod(m, struct ip *);
  654                 *mhip = *ip;
  655                 if (hlen > sizeof (struct ip)) {
  656                         mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip);
  657                         mhip->ip_vhl = IP_MAKE_VHL(IPVERSION, mhlen >> 2);
  658                 }
  659                 m->m_len = mhlen;
  660                 mhip->ip_off = ((off - hlen) >> 3) + (ip->ip_off & ~IP_MF);
  661                 if (ip->ip_off & IP_MF)
  662                         mhip->ip_off |= IP_MF;
  663                 if (off + len >= (u_short)ip->ip_len)
  664                         len = (u_short)ip->ip_len - off;
  665                 else
  666                         mhip->ip_off |= IP_MF;
  667                 mhip->ip_len = htons((u_short)(len + mhlen));
  668                 m->m_next = m_copy(m0, off, len);
  669                 if (m->m_next == 0) {
  670                         (void) m_free(m);
  671                         error = ENOBUFS;        /* ??? */
  672                         ipstat.ips_odropped++;
  673                         goto sendorfree;
  674                 }
  675                 m->m_pkthdr.len = mhlen + len;
  676                 m->m_pkthdr.rcvif = (struct ifnet *)0;
  677                 mhip->ip_off = htons((u_short)mhip->ip_off);
  678                 mhip->ip_sum = 0;
  679                 if (mhip->ip_vhl == IP_VHL_BORING) {
  680                         mhip->ip_sum = in_cksum_hdr(mhip);
  681                 } else {
  682                         mhip->ip_sum = in_cksum(m, mhlen);
  683                 }
  684                 *mnext = m;
  685                 mnext = &m->m_nextpkt;
  686                 ipstat.ips_ofragments++;
  687         }
  688         /*
  689          * Update first fragment by trimming what's been copied out
  690          * and updating header, then send each fragment (in order).
  691          */
  692         m = m0;
  693         m_adj(m, hlen + firstlen - (u_short)ip->ip_len);
  694         m->m_pkthdr.len = hlen + firstlen;
  695         ip->ip_len = htons((u_short)m->m_pkthdr.len);
  696         ip->ip_off = htons((u_short)(ip->ip_off | IP_MF));
  697         ip->ip_sum = 0;
  698         if (ip->ip_vhl == IP_VHL_BORING) {
  699                 ip->ip_sum = in_cksum_hdr(ip);
  700         } else {
  701                 ip->ip_sum = in_cksum(m, hlen);
  702         }
  703 sendorfree:
  704         for (m = m0; m; m = m0) {
  705                 m0 = m->m_nextpkt;
  706                 m->m_nextpkt = 0;
  707                 if (error == 0)
  708                         error = (*ifp->if_output)(ifp, m,
  709                             (struct sockaddr *)dst, ro->ro_rt);
  710                 else
  711                         m_freem(m);
  712         }
  713 
  714         if (error == 0)
  715                 ipstat.ips_fragmented++;
  716     }
  717 done:
  718         return (error);
  719 bad:
  720         m_freem(m0);
  721         goto done;
  722 }
  723 
  724 /*
  725  * Insert IP options into preformed packet.
  726  * Adjust IP destination as required for IP source routing,
  727  * as indicated by a non-zero in_addr at the start of the options.
  728  *
  729  * XXX This routine assumes that the packet has no options in place.
  730  */
  731 static struct mbuf *
  732 ip_insertoptions(m, opt, phlen)
  733         register struct mbuf *m;
  734         struct mbuf *opt;
  735         int *phlen;
  736 {
  737         register struct ipoption *p = mtod(opt, struct ipoption *);
  738         struct mbuf *n;
  739         register struct ip *ip = mtod(m, struct ip *);
  740         unsigned optlen;
  741 
  742         optlen = opt->m_len - sizeof(p->ipopt_dst);
  743         if (optlen + (u_short)ip->ip_len > IP_MAXPACKET)
  744                 return (m);             /* XXX should fail */
  745         if (p->ipopt_dst.s_addr)
  746                 ip->ip_dst = p->ipopt_dst;
  747         if (m->m_flags & M_EXT || m->m_data - optlen < m->m_pktdat) {
  748                 MGETHDR(n, M_DONTWAIT, MT_HEADER);
  749                 if (n == 0)
  750                         return (m);
  751                 n->m_pkthdr.rcvif = (struct ifnet *)0;
  752                 n->m_pkthdr.len = m->m_pkthdr.len + optlen;
  753                 m->m_len -= sizeof(struct ip);
  754                 m->m_data += sizeof(struct ip);
  755                 n->m_next = m;
  756                 m = n;
  757                 m->m_len = optlen + sizeof(struct ip);
  758                 m->m_data += max_linkhdr;
  759                 (void)memcpy(mtod(m, void *), ip, sizeof(struct ip));
  760         } else {
  761                 m->m_data -= optlen;
  762                 m->m_len += optlen;
  763                 m->m_pkthdr.len += optlen;
  764                 ovbcopy((caddr_t)ip, mtod(m, caddr_t), sizeof(struct ip));
  765         }
  766         ip = mtod(m, struct ip *);
  767         bcopy(p->ipopt_list, ip + 1, optlen);
  768         *phlen = sizeof(struct ip) + optlen;
  769         ip->ip_vhl = IP_MAKE_VHL(IPVERSION, *phlen >> 2);
  770         ip->ip_len += optlen;
  771         return (m);
  772 }
  773 
  774 /*
  775  * Copy options from ip to jp,
  776  * omitting those not copied during fragmentation.
  777  */
  778 #if !defined(IPFILTER) && !defined(IPFILTER_LKM)
  779 static
  780 #endif
  781 int
  782 ip_optcopy(ip, jp)
  783         struct ip *ip, *jp;
  784 {
  785         register u_char *cp, *dp;
  786         int opt, optlen, cnt;
  787 
  788         cp = (u_char *)(ip + 1);
  789         dp = (u_char *)(jp + 1);
  790         cnt = (IP_VHL_HL(ip->ip_vhl) << 2) - sizeof (struct ip);
  791         for (; cnt > 0; cnt -= optlen, cp += optlen) {
  792                 opt = cp[0];
  793                 if (opt == IPOPT_EOL)
  794                         break;
  795                 if (opt == IPOPT_NOP) {
  796                         /* Preserve for IP mcast tunnel's LSRR alignment. */
  797                         *dp++ = IPOPT_NOP;
  798                         optlen = 1;
  799                         continue;
  800                 } else
  801                         optlen = cp[IPOPT_OLEN];
  802                 /* bogus lengths should have been caught by ip_dooptions */
  803                 if (optlen > cnt)
  804                         optlen = cnt;
  805                 if (IPOPT_COPIED(opt)) {
  806                         bcopy(cp, dp, optlen);
  807                         dp += optlen;
  808                 }
  809         }
  810         for (optlen = dp - (u_char *)(jp+1); optlen & 0x3; optlen++)
  811                 *dp++ = IPOPT_EOL;
  812         return (optlen);
  813 }
  814 
  815 /*
  816  * IP socket option processing.
  817  */
  818 int
  819 ip_ctloutput(so, sopt)
  820         struct socket *so;
  821         struct sockopt *sopt;
  822 {
  823         struct  inpcb *inp = sotoinpcb(so);
  824         int     error, optval;
  825 
  826         error = optval = 0;
  827         if (sopt->sopt_level != IPPROTO_IP) {
  828                 return (EINVAL);
  829         }
  830 
  831         switch (sopt->sopt_dir) {
  832         case SOPT_SET:
  833                 switch (sopt->sopt_name) {
  834                 case IP_OPTIONS:
  835 #ifdef notyet
  836                 case IP_RETOPTS:
  837 #endif
  838                 {
  839                         struct mbuf *m;
  840                         if (sopt->sopt_valsize > MLEN) {
  841                                 error = EMSGSIZE;
  842                                 break;
  843                         }
  844                         MGET(m, sopt->sopt_p ? M_WAIT : M_DONTWAIT, MT_HEADER);
  845                         if (m == 0) {
  846                                 error = ENOBUFS;
  847                                 break;
  848                         }
  849                         m->m_len = sopt->sopt_valsize;
  850                         error = sooptcopyin(sopt, mtod(m, char *), m->m_len,
  851                                             m->m_len);
  852                         
  853                         return (ip_pcbopts(sopt->sopt_name, &inp->inp_options,
  854                                            m));
  855                 }
  856 
  857                 case IP_TOS:
  858                 case IP_TTL:
  859                 case IP_RECVOPTS:
  860                 case IP_RECVRETOPTS:
  861                 case IP_RECVDSTADDR:
  862                 case IP_RECVIF:
  863                         error = sooptcopyin(sopt, &optval, sizeof optval,
  864                                             sizeof optval);
  865                         if (error)
  866                                 break;
  867 
  868                         switch (sopt->sopt_name) {
  869                         case IP_TOS:
  870                                 inp->inp_ip_tos = optval;
  871                                 break;
  872 
  873                         case IP_TTL:
  874                                 inp->inp_ip_ttl = optval;
  875                                 break;
  876 #define OPTSET(bit) \
  877         if (optval) \
  878                 inp->inp_flags |= bit; \
  879         else \
  880                 inp->inp_flags &= ~bit;
  881 
  882                         case IP_RECVOPTS:
  883                                 OPTSET(INP_RECVOPTS);
  884                                 break;
  885 
  886                         case IP_RECVRETOPTS:
  887                                 OPTSET(INP_RECVRETOPTS);
  888                                 break;
  889 
  890                         case IP_RECVDSTADDR:
  891                                 OPTSET(INP_RECVDSTADDR);
  892                                 break;
  893 
  894                         case IP_RECVIF:
  895                                 OPTSET(INP_RECVIF);
  896                                 break;
  897                         }
  898                         break;
  899 #undef OPTSET
  900 
  901                 case IP_MULTICAST_IF:
  902                 case IP_MULTICAST_VIF:
  903                 case IP_MULTICAST_TTL:
  904                 case IP_MULTICAST_LOOP:
  905                 case IP_ADD_MEMBERSHIP:
  906                 case IP_DROP_MEMBERSHIP:
  907                         error = ip_setmoptions(sopt, &inp->inp_moptions);
  908                         break;
  909 
  910                 case IP_PORTRANGE:
  911                         error = sooptcopyin(sopt, &optval, sizeof optval,
  912                                             sizeof optval);
  913                         if (error)
  914                                 break;
  915 
  916                         switch (optval) {
  917                         case IP_PORTRANGE_DEFAULT:
  918                                 inp->inp_flags &= ~(INP_LOWPORT);
  919                                 inp->inp_flags &= ~(INP_HIGHPORT);
  920                                 break;
  921 
  922                         case IP_PORTRANGE_HIGH:
  923                                 inp->inp_flags &= ~(INP_LOWPORT);
  924                                 inp->inp_flags |= INP_HIGHPORT;
  925                                 break;
  926 
  927                         case IP_PORTRANGE_LOW:
  928                                 inp->inp_flags &= ~(INP_HIGHPORT);
  929                                 inp->inp_flags |= INP_LOWPORT;
  930                                 break;
  931 
  932                         default:
  933                                 error = EINVAL;
  934                                 break;
  935                         }
  936                         break;
  937 
  938                 default:
  939                         error = ENOPROTOOPT;
  940                         break;
  941                 }
  942                 break;
  943 
  944         case SOPT_GET:
  945                 switch (sopt->sopt_name) {
  946                 case IP_OPTIONS:
  947                 case IP_RETOPTS:
  948                         if (inp->inp_options)
  949                                 error = sooptcopyout(sopt, 
  950                                                      mtod(inp->inp_options,
  951                                                           char *),
  952                                                      inp->inp_options->m_len);
  953                         else
  954                                 sopt->sopt_valsize = 0;
  955                         break;
  956 
  957                 case IP_TOS:
  958                 case IP_TTL:
  959                 case IP_RECVOPTS:
  960                 case IP_RECVRETOPTS:
  961                 case IP_RECVDSTADDR:
  962                 case IP_RECVIF:
  963                 case IP_PORTRANGE:
  964                         switch (sopt->sopt_name) {
  965 
  966                         case IP_TOS:
  967                                 optval = inp->inp_ip_tos;
  968                                 break;
  969 
  970                         case IP_TTL:
  971                                 optval = inp->inp_ip_ttl;
  972                                 break;
  973 
  974 #define OPTBIT(bit)     (inp->inp_flags & bit ? 1 : 0)
  975 
  976                         case IP_RECVOPTS:
  977                                 optval = OPTBIT(INP_RECVOPTS);
  978                                 break;
  979 
  980                         case IP_RECVRETOPTS:
  981                                 optval = OPTBIT(INP_RECVRETOPTS);
  982                                 break;
  983 
  984                         case IP_RECVDSTADDR:
  985                                 optval = OPTBIT(INP_RECVDSTADDR);
  986                                 break;
  987 
  988                         case IP_RECVIF:
  989                                 optval = OPTBIT(INP_RECVIF);
  990                                 break;
  991 
  992                         case IP_PORTRANGE:
  993                                 if (inp->inp_flags & INP_HIGHPORT)
  994                                         optval = IP_PORTRANGE_HIGH;
  995                                 else if (inp->inp_flags & INP_LOWPORT)
  996                                         optval = IP_PORTRANGE_LOW;
  997                                 else
  998                                         optval = 0;
  999                                 break;
 1000                         }
 1001                         error = sooptcopyout(sopt, &optval, sizeof optval);
 1002                         break;
 1003 
 1004                 case IP_MULTICAST_IF:
 1005                 case IP_MULTICAST_VIF:
 1006                 case IP_MULTICAST_TTL:
 1007                 case IP_MULTICAST_LOOP:
 1008                 case IP_ADD_MEMBERSHIP:
 1009                 case IP_DROP_MEMBERSHIP:
 1010                         error = ip_getmoptions(sopt, inp->inp_moptions);
 1011                         break;
 1012 
 1013                 default:
 1014                         error = ENOPROTOOPT;
 1015                         break;
 1016                 }
 1017                 break;
 1018         }
 1019         return (error);
 1020 }
 1021 
 1022 /*
 1023  * Set up IP options in pcb for insertion in output packets.
 1024  * Store in mbuf with pointer in pcbopt, adding pseudo-option
 1025  * with destination address if source routed.
 1026  */
 1027 static int
 1028 ip_pcbopts(optname, pcbopt, m)
 1029         int optname;
 1030         struct mbuf **pcbopt;
 1031         register struct mbuf *m;
 1032 {
 1033         register int cnt, optlen;
 1034         register u_char *cp;
 1035         u_char opt;
 1036 
 1037         /* turn off any old options */
 1038         if (*pcbopt)
 1039                 (void)m_free(*pcbopt);
 1040         *pcbopt = 0;
 1041         if (m == (struct mbuf *)0 || m->m_len == 0) {
 1042                 /*
 1043                  * Only turning off any previous options.
 1044                  */
 1045                 if (m)
 1046                         (void)m_free(m);
 1047                 return (0);
 1048         }
 1049 
 1050 #ifndef vax
 1051         if (m->m_len % sizeof(int32_t))
 1052                 goto bad;
 1053 #endif
 1054         /*
 1055          * IP first-hop destination address will be stored before
 1056          * actual options; move other options back
 1057          * and clear it when none present.
 1058          */
 1059         if (m->m_data + m->m_len + sizeof(struct in_addr) >= &m->m_dat[MLEN])
 1060                 goto bad;
 1061         cnt = m->m_len;
 1062         m->m_len += sizeof(struct in_addr);
 1063         cp = mtod(m, u_char *) + sizeof(struct in_addr);
 1064         ovbcopy(mtod(m, caddr_t), (caddr_t)cp, (unsigned)cnt);
 1065         bzero(mtod(m, caddr_t), sizeof(struct in_addr));
 1066 
 1067         for (; cnt > 0; cnt -= optlen, cp += optlen) {
 1068                 opt = cp[IPOPT_OPTVAL];
 1069                 if (opt == IPOPT_EOL)
 1070                         break;
 1071                 if (opt == IPOPT_NOP)
 1072                         optlen = 1;
 1073                 else {
 1074                         if (cnt < IPOPT_OLEN + sizeof(*cp))
 1075                                 goto bad;
 1076                         optlen = cp[IPOPT_OLEN];
 1077                         if (optlen < IPOPT_OLEN + sizeof(*cp) || optlen > cnt)
 1078                                 goto bad;
 1079                 }
 1080                 switch (opt) {
 1081 
 1082                 default:
 1083                         break;
 1084 
 1085                 case IPOPT_LSRR:
 1086                 case IPOPT_SSRR:
 1087                         /*
 1088                          * user process specifies route as:
 1089                          *      ->A->B->C->D
 1090                          * D must be our final destination (but we can't
 1091                          * check that since we may not have connected yet).
 1092                          * A is first hop destination, which doesn't appear in
 1093                          * actual IP option, but is stored before the options.
 1094                          */
 1095                         if (optlen < IPOPT_MINOFF - 1 + sizeof(struct in_addr))
 1096                                 goto bad;
 1097                         m->m_len -= sizeof(struct in_addr);
 1098                         cnt -= sizeof(struct in_addr);
 1099                         optlen -= sizeof(struct in_addr);
 1100                         cp[IPOPT_OLEN] = optlen;
 1101                         /*
 1102                          * Move first hop before start of options.
 1103                          */
 1104                         bcopy((caddr_t)&cp[IPOPT_OFFSET+1], mtod(m, caddr_t),
 1105                             sizeof(struct in_addr));
 1106                         /*
 1107                          * Then copy rest of options back
 1108                          * to close up the deleted entry.
 1109                          */
 1110                         ovbcopy((caddr_t)(&cp[IPOPT_OFFSET+1] +
 1111                             sizeof(struct in_addr)),
 1112                             (caddr_t)&cp[IPOPT_OFFSET+1],
 1113                             (unsigned)cnt + sizeof(struct in_addr));
 1114                         break;
 1115                 }
 1116         }
 1117         if (m->m_len > MAX_IPOPTLEN + sizeof(struct in_addr))
 1118                 goto bad;
 1119         *pcbopt = m;
 1120         return (0);
 1121 
 1122 bad:
 1123         (void)m_free(m);
 1124         return (EINVAL);
 1125 }
 1126 
 1127 /*
 1128  * XXX
 1129  * The whole multicast option thing needs to be re-thought.
 1130  * Several of these options are equally applicable to non-multicast
 1131  * transmission, and one (IP_MULTICAST_TTL) totally duplicates a
 1132  * standard option (IP_TTL).
 1133  */
 1134 /*
 1135  * Set the IP multicast options in response to user setsockopt().
 1136  */
 1137 static int
 1138 ip_setmoptions(sopt, imop)
 1139         struct sockopt *sopt;
 1140         struct ip_moptions **imop;
 1141 {
 1142         int error = 0;
 1143         int i;
 1144         struct in_addr addr;
 1145         struct ip_mreq mreq;
 1146         struct ifnet *ifp;
 1147         struct ip_moptions *imo = *imop;
 1148         struct route ro;
 1149         struct sockaddr_in *dst;
 1150         int s;
 1151 
 1152         if (imo == NULL) {
 1153                 /*
 1154                  * No multicast option buffer attached to the pcb;
 1155                  * allocate one and initialize to default values.
 1156                  */
 1157                 imo = (struct ip_moptions*)malloc(sizeof(*imo), M_IPMOPTS,
 1158                     M_WAITOK);
 1159 
 1160                 if (imo == NULL)
 1161                         return (ENOBUFS);
 1162                 *imop = imo;
 1163                 imo->imo_multicast_ifp = NULL;
 1164                 imo->imo_multicast_vif = -1;
 1165                 imo->imo_multicast_ttl = IP_DEFAULT_MULTICAST_TTL;
 1166                 imo->imo_multicast_loop = IP_DEFAULT_MULTICAST_LOOP;
 1167                 imo->imo_num_memberships = 0;
 1168         }
 1169 
 1170         switch (sopt->sopt_name) {
 1171         /* store an index number for the vif you wanna use in the send */
 1172         case IP_MULTICAST_VIF:
 1173                 if (legal_vif_num == 0) {
 1174                         error = EOPNOTSUPP;
 1175                         break;
 1176                 }
 1177                 error = sooptcopyin(sopt, &i, sizeof i, sizeof i);
 1178                 if (error)
 1179                         break;
 1180                 if (!legal_vif_num(i) && (i != -1)) {
 1181                         error = EINVAL;
 1182                         break;
 1183                 }
 1184                 imo->imo_multicast_vif = i;
 1185                 break;
 1186 
 1187         case IP_MULTICAST_IF:
 1188                 /*
 1189                  * Select the interface for outgoing multicast packets.
 1190                  */
 1191                 error = sooptcopyin(sopt, &addr, sizeof addr, sizeof addr);
 1192                 if (error)
 1193                         break;
 1194                 /*
 1195                  * INADDR_ANY is used to remove a previous selection.
 1196                  * When no interface is selected, a default one is
 1197                  * chosen every time a multicast packet is sent.
 1198                  */
 1199                 if (addr.s_addr == INADDR_ANY) {
 1200                         imo->imo_multicast_ifp = NULL;
 1201                         break;
 1202                 }
 1203                 /*
 1204                  * The selected interface is identified by its local
 1205                  * IP address.  Find the interface and confirm that
 1206                  * it supports multicasting.
 1207                  */
 1208                 s = splimp();
 1209                 INADDR_TO_IFP(addr, ifp);
 1210                 if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0) {
 1211                         splx(s);
 1212                         error = EADDRNOTAVAIL;
 1213                         break;
 1214                 }
 1215                 imo->imo_multicast_ifp = ifp;
 1216                 splx(s);
 1217                 break;
 1218 
 1219         case IP_MULTICAST_TTL:
 1220                 /*
 1221                  * Set the IP time-to-live for outgoing multicast packets.
 1222                  * The original multicast API required a char argument,
 1223                  * which is inconsistent with the rest of the socket API.
 1224                  * We allow either a char or an int.
 1225                  */
 1226                 if (sopt->sopt_valsize == 1) {
 1227                         u_char ttl;
 1228                         error = sooptcopyin(sopt, &ttl, 1, 1);
 1229                         if (error)
 1230                                 break;
 1231                         imo->imo_multicast_ttl = ttl;
 1232                 } else {
 1233                         u_int ttl;
 1234                         error = sooptcopyin(sopt, &ttl, sizeof ttl, 
 1235                                             sizeof ttl);
 1236                         if (error)
 1237                                 break;
 1238                         if (ttl > 255)
 1239                                 error = EINVAL;
 1240                         else
 1241                                 imo->imo_multicast_ttl = ttl;
 1242                 }
 1243                 break;
 1244 
 1245         case IP_MULTICAST_LOOP:
 1246                 /*
 1247                  * Set the loopback flag for outgoing multicast packets.
 1248                  * Must be zero or one.  The original multicast API required a
 1249                  * char argument, which is inconsistent with the rest
 1250                  * of the socket API.  We allow either a char or an int.
 1251                  */
 1252                 if (sopt->sopt_valsize == 1) {
 1253                         u_char loop;
 1254                         error = sooptcopyin(sopt, &loop, 1, 1);
 1255                         if (error)
 1256                                 break;
 1257                         imo->imo_multicast_loop = !!loop;
 1258                 } else {
 1259                         u_int loop;
 1260                         error = sooptcopyin(sopt, &loop, sizeof loop,
 1261                                             sizeof loop);
 1262                         if (error)
 1263                                 break;
 1264                         imo->imo_multicast_loop = !!loop;
 1265                 }
 1266                 break;
 1267 
 1268         case IP_ADD_MEMBERSHIP:
 1269                 /*
 1270                  * Add a multicast group membership.
 1271                  * Group must be a valid IP multicast address.
 1272                  */
 1273                 error = sooptcopyin(sopt, &mreq, sizeof mreq, sizeof mreq);
 1274                 if (error)
 1275                         break;
 1276 
 1277                 if (!IN_MULTICAST(ntohl(mreq.imr_multiaddr.s_addr))) {
 1278                         error = EINVAL;
 1279                         break;
 1280                 }
 1281                 s = splimp();
 1282                 /*
 1283                  * If no interface address was provided, use the interface of
 1284                  * the route to the given multicast address.
 1285                  */
 1286                 if (mreq.imr_interface.s_addr == INADDR_ANY) {
 1287                         bzero((caddr_t)&ro, sizeof(ro));
 1288                         dst = (struct sockaddr_in *)&ro.ro_dst;
 1289                         dst->sin_len = sizeof(*dst);
 1290                         dst->sin_family = AF_INET;
 1291                         dst->sin_addr = mreq.imr_multiaddr;
 1292                         rtalloc(&ro);
 1293                         if (ro.ro_rt == NULL) {
 1294                                 error = EADDRNOTAVAIL;
 1295                                 splx(s);
 1296                                 break;
 1297                         }
 1298                         ifp = ro.ro_rt->rt_ifp;
 1299                         rtfree(ro.ro_rt);
 1300                 }
 1301                 else {
 1302                         INADDR_TO_IFP(mreq.imr_interface, ifp);
 1303                 }
 1304 
 1305                 /*
 1306                  * See if we found an interface, and confirm that it
 1307                  * supports multicast.
 1308                  */
 1309                 if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0) {
 1310                         error = EADDRNOTAVAIL;
 1311                         splx(s);
 1312                         break;
 1313                 }
 1314                 /*
 1315                  * See if the membership already exists or if all the
 1316                  * membership slots are full.
 1317                  */
 1318                 for (i = 0; i < imo->imo_num_memberships; ++i) {
 1319                         if (imo->imo_membership[i]->inm_ifp == ifp &&
 1320                             imo->imo_membership[i]->inm_addr.s_addr
 1321                                                 == mreq.imr_multiaddr.s_addr)
 1322                                 break;
 1323                 }
 1324                 if (i < imo->imo_num_memberships) {
 1325                         error = EADDRINUSE;
 1326                         splx(s);
 1327                         break;
 1328                 }
 1329                 if (i == IP_MAX_MEMBERSHIPS) {
 1330                         error = ETOOMANYREFS;
 1331                         splx(s);
 1332                         break;
 1333                 }
 1334                 /*
 1335                  * Everything looks good; add a new record to the multicast
 1336                  * address list for the given interface.
 1337                  */
 1338                 if ((imo->imo_membership[i] =
 1339                     in_addmulti(&mreq.imr_multiaddr, ifp)) == NULL) {
 1340                         error = ENOBUFS;
 1341                         splx(s);
 1342                         break;
 1343                 }
 1344                 ++imo->imo_num_memberships;
 1345                 splx(s);
 1346                 break;
 1347 
 1348         case IP_DROP_MEMBERSHIP:
 1349                 /*
 1350                  * Drop a multicast group membership.
 1351                  * Group must be a valid IP multicast address.
 1352                  */
 1353                 error = sooptcopyin(sopt, &mreq, sizeof mreq, sizeof mreq);
 1354                 if (error)
 1355                         break;
 1356 
 1357                 if (!IN_MULTICAST(ntohl(mreq.imr_multiaddr.s_addr))) {
 1358                         error = EINVAL;
 1359                         break;
 1360                 }
 1361 
 1362                 s = splimp();
 1363                 /*
 1364                  * If an interface address was specified, get a pointer
 1365                  * to its ifnet structure.
 1366                  */
 1367                 if (mreq.imr_interface.s_addr == INADDR_ANY)
 1368                         ifp = NULL;
 1369                 else {
 1370                         INADDR_TO_IFP(mreq.imr_interface, ifp);
 1371                         if (ifp == NULL) {
 1372                                 error = EADDRNOTAVAIL;
 1373                                 splx(s);
 1374                                 break;
 1375                         }
 1376                 }
 1377                 /*
 1378                  * Find the membership in the membership array.
 1379                  */
 1380                 for (i = 0; i < imo->imo_num_memberships; ++i) {
 1381                         if ((ifp == NULL ||
 1382                              imo->imo_membership[i]->inm_ifp == ifp) &&
 1383                              imo->imo_membership[i]->inm_addr.s_addr ==
 1384                              mreq.imr_multiaddr.s_addr)
 1385                                 break;
 1386                 }
 1387                 if (i == imo->imo_num_memberships) {
 1388                         error = EADDRNOTAVAIL;
 1389                         splx(s);
 1390                         break;
 1391                 }
 1392                 /*
 1393                  * Give up the multicast address record to which the
 1394                  * membership points.
 1395                  */
 1396                 in_delmulti(imo->imo_membership[i]);
 1397                 /*
 1398                  * Remove the gap in the membership array.
 1399                  */
 1400                 for (++i; i < imo->imo_num_memberships; ++i)
 1401                         imo->imo_membership[i-1] = imo->imo_membership[i];
 1402                 --imo->imo_num_memberships;
 1403                 splx(s);
 1404                 break;
 1405 
 1406         default:
 1407                 error = EOPNOTSUPP;
 1408                 break;
 1409         }
 1410 
 1411         /*
 1412          * If all options have default values, no need to keep the mbuf.
 1413          */
 1414         if (imo->imo_multicast_ifp == NULL &&
 1415             imo->imo_multicast_vif == -1 &&
 1416             imo->imo_multicast_ttl == IP_DEFAULT_MULTICAST_TTL &&
 1417             imo->imo_multicast_loop == IP_DEFAULT_MULTICAST_LOOP &&
 1418             imo->imo_num_memberships == 0) {
 1419                 free(*imop, M_IPMOPTS);
 1420                 *imop = NULL;
 1421         }
 1422 
 1423         return (error);
 1424 }
 1425 
 1426 /*
 1427  * Return the IP multicast options in response to user getsockopt().
 1428  */
 1429 static int
 1430 ip_getmoptions(sopt, imo)
 1431         struct sockopt *sopt;
 1432         register struct ip_moptions *imo;
 1433 {
 1434         struct in_addr addr;
 1435         struct in_ifaddr *ia;
 1436         int error, optval;
 1437         u_char coptval;
 1438 
 1439         error = 0;
 1440         switch (sopt->sopt_name) {
 1441         case IP_MULTICAST_VIF: 
 1442                 if (imo != NULL)
 1443                         optval = imo->imo_multicast_vif;
 1444                 else
 1445                         optval = -1;
 1446                 error = sooptcopyout(sopt, &optval, sizeof optval);
 1447                 break;
 1448 
 1449         case IP_MULTICAST_IF:
 1450                 if (imo == NULL || imo->imo_multicast_ifp == NULL)
 1451                         addr.s_addr = INADDR_ANY;
 1452                 else {
 1453                         IFP_TO_IA(imo->imo_multicast_ifp, ia);
 1454                         addr.s_addr = (ia == NULL) ? INADDR_ANY
 1455                                 : IA_SIN(ia)->sin_addr.s_addr;
 1456                 }
 1457                 error = sooptcopyout(sopt, &addr, sizeof addr);
 1458                 break;
 1459 
 1460         case IP_MULTICAST_TTL:
 1461                 if (imo == 0)
 1462                         optval = coptval = IP_DEFAULT_MULTICAST_TTL;
 1463                 else
 1464                         optval = coptval = imo->imo_multicast_ttl;
 1465                 if (sopt->sopt_valsize == 1)
 1466                         error = sooptcopyout(sopt, &coptval, 1);
 1467                 else
 1468                         error = sooptcopyout(sopt, &optval, sizeof optval);
 1469                 break;
 1470 
 1471         case IP_MULTICAST_LOOP:
 1472                 if (imo == 0)
 1473                         optval = coptval = IP_DEFAULT_MULTICAST_LOOP;
 1474                 else
 1475                         optval = coptval = imo->imo_multicast_loop;
 1476                 if (sopt->sopt_valsize == 1)
 1477                         error = sooptcopyout(sopt, &coptval, 1);
 1478                 else
 1479                         error = sooptcopyout(sopt, &optval, sizeof optval);
 1480                 break;
 1481 
 1482         default:
 1483                 error = ENOPROTOOPT;
 1484                 break;
 1485         }
 1486         return (error);
 1487 }
 1488 
 1489 /*
 1490  * Discard the IP multicast options.
 1491  */
 1492 void
 1493 ip_freemoptions(imo)
 1494         register struct ip_moptions *imo;
 1495 {
 1496         register int i;
 1497 
 1498         if (imo != NULL) {
 1499                 for (i = 0; i < imo->imo_num_memberships; ++i)
 1500                         in_delmulti(imo->imo_membership[i]);
 1501                 free(imo, M_IPMOPTS);
 1502         }
 1503 }
 1504 
 1505 /*
 1506  * Routine called from ip_output() to loop back a copy of an IP multicast
 1507  * packet to the input queue of a specified interface.  Note that this
 1508  * calls the output routine of the loopback "driver", but with an interface
 1509  * pointer that might NOT be a loopback interface -- evil, but easier than
 1510  * replicating that code here.
 1511  */
 1512 static void
 1513 ip_mloopback(ifp, m, dst, hlen)
 1514         struct ifnet *ifp;
 1515         register struct mbuf *m;
 1516         register struct sockaddr_in *dst;
 1517         int hlen;
 1518 {
 1519         register struct ip *ip;
 1520         struct mbuf *copym;
 1521 
 1522         copym = m_copy(m, 0, M_COPYALL);
 1523         if (copym != NULL && (copym->m_flags & M_EXT || copym->m_len < hlen))
 1524                 copym = m_pullup(copym, hlen);
 1525         if (copym != NULL) {
 1526                 /*
 1527                  * We don't bother to fragment if the IP length is greater
 1528                  * than the interface's MTU.  Can this possibly matter?
 1529                  */
 1530                 ip = mtod(copym, struct ip *);
 1531                 ip->ip_len = htons((u_short)ip->ip_len);
 1532                 ip->ip_off = htons((u_short)ip->ip_off);
 1533                 ip->ip_sum = 0;
 1534                 if (ip->ip_vhl == IP_VHL_BORING) {
 1535                         ip->ip_sum = in_cksum_hdr(ip);
 1536                 } else {
 1537                         ip->ip_sum = in_cksum(copym, hlen);
 1538                 }
 1539                 /*
 1540                  * NB:
 1541                  * It's not clear whether there are any lingering
 1542                  * reentrancy problems in other areas which might
 1543                  * be exposed by using ip_input directly (in
 1544                  * particular, everything which modifies the packet
 1545                  * in-place).  Yet another option is using the
 1546                  * protosw directly to deliver the looped back
 1547                  * packet.  For the moment, we'll err on the side
 1548                  * of safety by using if_simloop().
 1549                  */
 1550 #if 1 /* XXX */
 1551                 if (dst->sin_family != AF_INET) {
 1552                         printf("ip_mloopback: bad address family %d\n",
 1553                                                 dst->sin_family);
 1554                         dst->sin_family = AF_INET;
 1555                 }
 1556 #endif
 1557 
 1558 #ifdef notdef
 1559                 copym->m_pkthdr.rcvif = ifp;
 1560                 ip_input(copym);
 1561 #else
 1562                 if_simloop(ifp, copym, (struct sockaddr *)dst, 0);
 1563 #endif
 1564         }
 1565 }

Cache object: cbb21c57a464ff33316a9e5111bc96b2


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.