LCOV - code coverage report
Current view: top level - netinet - ip_output.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 813 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 15 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: ip_output.c,v 1.348 2018/08/28 15:15:02 mpi Exp $     */
       2             : /*      $NetBSD: ip_output.c,v 1.28 1996/02/13 23:43:07 christos Exp $  */
       3             : 
       4             : /*
       5             :  * Copyright (c) 1982, 1986, 1988, 1990, 1993
       6             :  *      The Regents of the University of California.  All rights reserved.
       7             :  *
       8             :  * Redistribution and use in source and binary forms, with or without
       9             :  * modification, are permitted provided that the following conditions
      10             :  * are met:
      11             :  * 1. Redistributions of source code must retain the above copyright
      12             :  *    notice, this list of conditions and the following disclaimer.
      13             :  * 2. Redistributions in binary form must reproduce the above copyright
      14             :  *    notice, this list of conditions and the following disclaimer in the
      15             :  *    documentation and/or other materials provided with the distribution.
      16             :  * 3. Neither the name of the University nor the names of its contributors
      17             :  *    may be used to endorse or promote products derived from this software
      18             :  *    without specific prior written permission.
      19             :  *
      20             :  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
      21             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      22             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      23             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
      24             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      25             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      26             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      27             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      28             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      29             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      30             :  * SUCH DAMAGE.
      31             :  *
      32             :  *      @(#)ip_output.c 8.3 (Berkeley) 1/21/94
      33             :  */
      34             : 
      35             : #include "pf.h"
      36             : 
      37             : #include <sys/param.h>
      38             : #include <sys/systm.h>
      39             : #include <sys/mbuf.h>
      40             : #include <sys/protosw.h>
      41             : #include <sys/socket.h>
      42             : #include <sys/socketvar.h>
      43             : #include <sys/proc.h>
      44             : #include <sys/kernel.h>
      45             : 
      46             : #include <net/if.h>
      47             : #include <net/if_var.h>
      48             : #include <net/if_enc.h>
      49             : #include <net/route.h>
      50             : 
      51             : #include <netinet/in.h>
      52             : #include <netinet/ip.h>
      53             : #include <netinet/in_pcb.h>
      54             : #include <netinet/in_var.h>
      55             : #include <netinet/ip_var.h>
      56             : #include <netinet/ip_icmp.h>
      57             : #include <netinet/tcp.h>
      58             : #include <netinet/udp.h>
      59             : #include <netinet/tcp_timer.h>
      60             : #include <netinet/tcp_var.h>
      61             : #include <netinet/udp_var.h>
      62             : 
      63             : #if NPF > 0
      64             : #include <net/pfvar.h>
      65             : #endif
      66             : 
      67             : #ifdef IPSEC
      68             : #ifdef ENCDEBUG
      69             : #define DPRINTF(x)    do { if (encdebug) printf x ; } while (0)
      70             : #else
      71             : #define DPRINTF(x)
      72             : #endif
      73             : #endif /* IPSEC */
      74             : 
      75             : int ip_pcbopts(struct mbuf **, struct mbuf *);
      76             : int ip_setmoptions(int, struct ip_moptions **, struct mbuf *, u_int);
      77             : void ip_mloopback(struct ifnet *, struct mbuf *, struct sockaddr_in *);
      78             : static __inline u_int16_t __attribute__((__unused__))
      79             :     in_cksum_phdr(u_int32_t, u_int32_t, u_int32_t);
      80             : void in_delayed_cksum(struct mbuf *);
      81             : 
      82             : #ifdef IPSEC
      83             : struct tdb *
      84             : ip_output_ipsec_lookup(struct mbuf *m, int hlen, int *error, struct inpcb *inp,
      85             :     int ipsecflowinfo);
      86             : int
      87             : ip_output_ipsec_send(struct tdb *, struct mbuf *, struct route *, int);
      88             : #endif /* IPSEC */
      89             : 
      90             : /*
      91             :  * IP output.  The packet in mbuf chain m contains a skeletal IP
      92             :  * header (with len, off, ttl, proto, tos, src, dst).
      93             :  * The mbuf chain containing the packet will be freed.
      94             :  * The mbuf opt, if present, will not be freed.
      95             :  */
      96             : int
      97           0 : ip_output(struct mbuf *m0, struct mbuf *opt, struct route *ro, int flags,
      98             :     struct ip_moptions *imo, struct inpcb *inp, u_int32_t ipsecflowinfo)
      99             : {
     100             :         struct ip *ip;
     101             :         struct ifnet *ifp = NULL;
     102           0 :         struct mbuf *m = m0;
     103             :         int hlen = sizeof (struct ip);
     104           0 :         int len, error = 0;
     105           0 :         struct route iproute;
     106             :         struct sockaddr_in *dst;
     107             :         struct tdb *tdb = NULL;
     108             :         u_long mtu;
     109             : #if defined(MROUTING)
     110             :         int rv;
     111             : #endif
     112             : 
     113           0 :         NET_ASSERT_LOCKED();
     114             : 
     115             : #ifdef IPSEC
     116           0 :         if (inp && (inp->inp_flags & INP_IPV6) != 0)
     117           0 :                 panic("ip_output: IPv6 pcb is passed");
     118             : #endif /* IPSEC */
     119             : 
     120             : #ifdef  DIAGNOSTIC
     121           0 :         if ((m->m_flags & M_PKTHDR) == 0)
     122           0 :                 panic("ip_output no HDR");
     123             : #endif
     124           0 :         if (opt) {
     125           0 :                 m = ip_insertoptions(m, opt, &len);
     126           0 :                 hlen = len;
     127           0 :         }
     128             : 
     129           0 :         ip = mtod(m, struct ip *);
     130             : 
     131             :         /*
     132             :          * Fill in IP header.
     133             :          */
     134           0 :         if ((flags & (IP_FORWARDING|IP_RAWOUTPUT)) == 0) {
     135           0 :                 ip->ip_v = IPVERSION;
     136           0 :                 ip->ip_off &= htons(IP_DF);
     137           0 :                 ip->ip_id = htons(ip_randomid());
     138           0 :                 ip->ip_hl = hlen >> 2;
     139           0 :                 ipstat_inc(ips_localout);
     140           0 :         } else {
     141           0 :                 hlen = ip->ip_hl << 2;
     142             :         }
     143             : 
     144             :         /*
     145             :          * We should not send traffic to 0/8 say both Stevens and RFCs
     146             :          * 5735 section 3 and 1122 sections 3.2.1.3 and 3.3.6.
     147             :          */
     148           0 :         if ((ntohl(ip->ip_dst.s_addr) >> IN_CLASSA_NSHIFT) == 0) {
     149           0 :                 error = ENETUNREACH;
     150           0 :                 goto bad;
     151             :         }
     152             : 
     153             : #if NPF > 0
     154             : reroute:
     155             : #endif
     156             : 
     157             :         /*
     158             :          * Do a route lookup now in case we need the source address to
     159             :          * do an SPD lookup in IPsec; for most packets, the source address
     160             :          * is set at a higher level protocol. ICMPs and other packets
     161             :          * though (e.g., traceroute) have a source address of zeroes.
     162             :          */
     163           0 :         if (ro == NULL) {
     164             :                 ro = &iproute;
     165           0 :                 memset(ro, 0, sizeof(*ro));
     166           0 :         }
     167             : 
     168           0 :         dst = satosin(&ro->ro_dst);
     169             : 
     170             :         /*
     171             :          * If there is a cached route, check that it is to the same
     172             :          * destination and is still up.  If not, free it and try again.
     173             :          */
     174           0 :         if (!rtisvalid(ro->ro_rt) ||
     175           0 :             dst->sin_addr.s_addr != ip->ip_dst.s_addr ||
     176           0 :             ro->ro_tableid != m->m_pkthdr.ph_rtableid) {
     177           0 :                 rtfree(ro->ro_rt);
     178           0 :                 ro->ro_rt = NULL;
     179           0 :         }
     180             : 
     181           0 :         if (ro->ro_rt == NULL) {
     182           0 :                 dst->sin_family = AF_INET;
     183           0 :                 dst->sin_len = sizeof(*dst);
     184           0 :                 dst->sin_addr = ip->ip_dst;
     185           0 :                 ro->ro_tableid = m->m_pkthdr.ph_rtableid;
     186           0 :         }
     187             : 
     188           0 :         if ((IN_MULTICAST(ip->ip_dst.s_addr) ||
     189           0 :             (ip->ip_dst.s_addr == INADDR_BROADCAST)) &&
     190           0 :             imo != NULL && (ifp = if_get(imo->imo_ifidx)) != NULL) {
     191             : 
     192           0 :                 mtu = ifp->if_mtu;
     193           0 :                 if (ip->ip_src.s_addr == INADDR_ANY) {
     194             :                         struct in_ifaddr *ia;
     195             : 
     196           0 :                         IFP_TO_IA(ifp, ia);
     197           0 :                         if (ia != NULL)
     198           0 :                                 ip->ip_src = ia->ia_addr.sin_addr;
     199           0 :                 }
     200             :         } else {
     201             :                 struct in_ifaddr *ia;
     202             : 
     203           0 :                 if (ro->ro_rt == NULL)
     204           0 :                         ro->ro_rt = rtalloc_mpath(&ro->ro_dst,
     205           0 :                             &ip->ip_src.s_addr, ro->ro_tableid);
     206             : 
     207           0 :                 if (ro->ro_rt == NULL) {
     208           0 :                         ipstat_inc(ips_noroute);
     209           0 :                         error = EHOSTUNREACH;
     210           0 :                         goto bad;
     211             :                 }
     212             : 
     213           0 :                 ia = ifatoia(ro->ro_rt->rt_ifa);
     214           0 :                 if (ISSET(ro->ro_rt->rt_flags, RTF_LOCAL))
     215           0 :                         ifp = if_get(rtable_loindex(m->m_pkthdr.ph_rtableid));
     216             :                 else
     217           0 :                         ifp = if_get(ro->ro_rt->rt_ifidx);
     218             :                 /*
     219             :                  * We aren't using rtisvalid() here because the UP/DOWN state
     220             :                  * machine is broken with some Ethernet drivers like em(4).
     221             :                  * As a result we might try to use an invalid cached route
     222             :                  * entry while an interface is being detached.
     223             :                  */
     224           0 :                 if (ifp == NULL) {
     225           0 :                         ipstat_inc(ips_noroute);
     226           0 :                         error = EHOSTUNREACH;
     227           0 :                         goto bad;
     228             :                 }
     229           0 :                 if ((mtu = ro->ro_rt->rt_mtu) == 0)
     230           0 :                         mtu = ifp->if_mtu;
     231             : 
     232           0 :                 if (ro->ro_rt->rt_flags & RTF_GATEWAY)
     233           0 :                         dst = satosin(ro->ro_rt->rt_gateway);
     234             : 
     235             :                 /* Set the source IP address */
     236           0 :                 if (ip->ip_src.s_addr == INADDR_ANY && ia)
     237           0 :                         ip->ip_src = ia->ia_addr.sin_addr;
     238           0 :         }
     239             : 
     240             : #ifdef IPSEC
     241           0 :         if (ipsec_in_use || inp != NULL) {
     242             :                 /* Do we have any pending SAs to apply ? */
     243           0 :                 tdb = ip_output_ipsec_lookup(m, hlen, &error, inp,
     244             :                     ipsecflowinfo);
     245           0 :                 if (error != 0) {
     246             :                         /* Should silently drop packet */
     247           0 :                         if (error == -EINVAL)
     248           0 :                                 error = 0;
     249           0 :                         m_freem(m);
     250           0 :                         goto done;
     251             :                 }
     252           0 :                 if (tdb != NULL) {
     253             :                         /*
     254             :                          * If it needs TCP/UDP hardware-checksumming, do the
     255             :                          * computation now.
     256             :                          */
     257           0 :                         in_proto_cksum_out(m, NULL);
     258           0 :                 }
     259             :         }
     260             : #endif /* IPSEC */
     261             : 
     262           0 :         if (IN_MULTICAST(ip->ip_dst.s_addr) ||
     263           0 :             (ip->ip_dst.s_addr == INADDR_BROADCAST)) {
     264             : 
     265           0 :                 m->m_flags |= (ip->ip_dst.s_addr == INADDR_BROADCAST) ?
     266             :                         M_BCAST : M_MCAST;
     267             : 
     268             :                 /*
     269             :                  * IP destination address is multicast.  Make sure "dst"
     270             :                  * still points to the address in "ro".  (It may have been
     271             :                  * changed to point to a gateway address, above.)
     272             :                  */
     273           0 :                 dst = satosin(&ro->ro_dst);
     274             : 
     275             :                 /*
     276             :                  * See if the caller provided any multicast options
     277             :                  */
     278           0 :                 if (imo != NULL)
     279           0 :                         ip->ip_ttl = imo->imo_ttl;
     280             :                 else
     281           0 :                         ip->ip_ttl = IP_DEFAULT_MULTICAST_TTL;
     282             : 
     283             :                 /*
     284             :                  * if we don't know the outgoing ifp yet, we can't generate
     285             :                  * output
     286             :                  */
     287           0 :                 if (!ifp) {
     288           0 :                         ipstat_inc(ips_noroute);
     289           0 :                         error = EHOSTUNREACH;
     290           0 :                         goto bad;
     291             :                 }
     292             : 
     293             :                 /*
     294             :                  * Confirm that the outgoing interface supports multicast,
     295             :                  * but only if the packet actually is going out on that
     296             :                  * interface (i.e., no IPsec is applied).
     297             :                  */
     298           0 :                 if ((((m->m_flags & M_MCAST) &&
     299           0 :                       (ifp->if_flags & IFF_MULTICAST) == 0) ||
     300           0 :                      ((m->m_flags & M_BCAST) &&
     301           0 :                       (ifp->if_flags & IFF_BROADCAST) == 0)) && (tdb == NULL)) {
     302           0 :                         ipstat_inc(ips_noroute);
     303           0 :                         error = ENETUNREACH;
     304           0 :                         goto bad;
     305             :                 }
     306             : 
     307             :                 /*
     308             :                  * If source address not specified yet, use address
     309             :                  * of outgoing interface.
     310             :                  */
     311           0 :                 if (ip->ip_src.s_addr == INADDR_ANY) {
     312             :                         struct in_ifaddr *ia;
     313             : 
     314           0 :                         IFP_TO_IA(ifp, ia);
     315           0 :                         if (ia != NULL)
     316           0 :                                 ip->ip_src = ia->ia_addr.sin_addr;
     317           0 :                 }
     318             : 
     319           0 :                 if ((imo == NULL || imo->imo_loop) &&
     320           0 :                     in_hasmulti(&ip->ip_dst, ifp)) {
     321             :                         /*
     322             :                          * If we belong to the destination multicast group
     323             :                          * on the outgoing interface, and the caller did not
     324             :                          * forbid loopback, loop back a copy.
     325             :                          * Can't defer TCP/UDP checksumming, do the
     326             :                          * computation now.
     327             :                          */
     328           0 :                         in_proto_cksum_out(m, NULL);
     329           0 :                         ip_mloopback(ifp, m, dst);
     330           0 :                 }
     331             : #ifdef MROUTING
     332             :                 else {
     333             :                         /*
     334             :                          * If we are acting as a multicast router, perform
     335             :                          * multicast forwarding as if the packet had just
     336             :                          * arrived on the interface to which we are about
     337             :                          * to send.  The multicast forwarding function
     338             :                          * recursively calls this function, using the
     339             :                          * IP_FORWARDING flag to prevent infinite recursion.
     340             :                          *
     341             :                          * Multicasts that are looped back by ip_mloopback(),
     342             :                          * above, will be forwarded by the ip_input() routine,
     343             :                          * if necessary.
     344             :                          */
     345           0 :                         if (ipmforwarding && ip_mrouter[ifp->if_rdomain] &&
     346           0 :                             (flags & IP_FORWARDING) == 0) {
     347           0 :                                 KERNEL_LOCK();
     348           0 :                                 rv = ip_mforward(m, ifp);
     349           0 :                                 KERNEL_UNLOCK();
     350           0 :                                 if (rv != 0) {
     351           0 :                                         m_freem(m);
     352           0 :                                         goto done;
     353             :                                 }
     354             :                         }
     355             :                 }
     356             : #endif
     357             :                 /*
     358             :                  * Multicasts with a time-to-live of zero may be looped-
     359             :                  * back, above, but must not be transmitted on a network.
     360             :                  * Also, multicasts addressed to the loopback interface
     361             :                  * are not sent -- the above call to ip_mloopback() will
     362             :                  * loop back a copy if this host actually belongs to the
     363             :                  * destination group on the loopback interface.
     364             :                  */
     365           0 :                 if (ip->ip_ttl == 0 || (ifp->if_flags & IFF_LOOPBACK) != 0) {
     366           0 :                         m_freem(m);
     367           0 :                         goto done;
     368             :                 }
     369             : 
     370             :                 goto sendit;
     371             :         }
     372             : 
     373             :         /*
     374             :          * Look for broadcast address and verify user is allowed to send
     375             :          * such a packet; if the packet is going in an IPsec tunnel, skip
     376             :          * this check.
     377             :          */
     378           0 :         if ((tdb == NULL) && ((dst->sin_addr.s_addr == INADDR_BROADCAST) ||
     379           0 :             (ro && ro->ro_rt && ISSET(ro->ro_rt->rt_flags, RTF_BROADCAST)))) {
     380           0 :                 if ((ifp->if_flags & IFF_BROADCAST) == 0) {
     381           0 :                         error = EADDRNOTAVAIL;
     382           0 :                         goto bad;
     383             :                 }
     384           0 :                 if ((flags & IP_ALLOWBROADCAST) == 0) {
     385           0 :                         error = EACCES;
     386           0 :                         goto bad;
     387             :                 }
     388             : 
     389             :                 /* Don't allow broadcast messages to be fragmented */
     390           0 :                 if (ntohs(ip->ip_len) > ifp->if_mtu) {
     391           0 :                         error = EMSGSIZE;
     392           0 :                         goto bad;
     393             :                 }
     394           0 :                 m->m_flags |= M_BCAST;
     395           0 :         } else
     396           0 :                 m->m_flags &= ~M_BCAST;
     397             : 
     398             : sendit:
     399             :         /*
     400             :          * If we're doing Path MTU discovery, we need to set DF unless
     401             :          * the route's MTU is locked.
     402             :          */
     403           0 :         if ((flags & IP_MTUDISC) && ro && ro->ro_rt &&
     404           0 :             (ro->ro_rt->rt_locks & RTV_MTU) == 0)
     405           0 :                 ip->ip_off |= htons(IP_DF);
     406             : 
     407             : #ifdef IPSEC
     408             :         /*
     409             :          * Check if the packet needs encapsulation.
     410             :          */
     411           0 :         if (tdb != NULL) {
     412             :                 /* Callee frees mbuf */
     413           0 :                 error = ip_output_ipsec_send(tdb, m, ro,
     414           0 :                     (flags & IP_FORWARDING) ? 1 : 0);
     415           0 :                 goto done;
     416             :         }
     417             : #endif /* IPSEC */
     418             : 
     419             :         /*
     420             :          * Packet filter
     421             :          */
     422             : #if NPF > 0
     423           0 :         if (pf_test(AF_INET, (flags & IP_FORWARDING) ? PF_FWD : PF_OUT,
     424           0 :             ifp, &m) != PF_PASS) {
     425           0 :                 error = EACCES;
     426           0 :                 m_freem(m);
     427           0 :                 goto done;
     428             :         }
     429           0 :         if (m == NULL)
     430             :                 goto done;
     431           0 :         ip = mtod(m, struct ip *);
     432           0 :         hlen = ip->ip_hl << 2;
     433           0 :         if ((m->m_pkthdr.pf.flags & (PF_TAG_REROUTE | PF_TAG_GENERATED)) ==
     434             :             (PF_TAG_REROUTE | PF_TAG_GENERATED))
     435             :                 /* already rerun the route lookup, go on */
     436           0 :                 m->m_pkthdr.pf.flags &= ~(PF_TAG_GENERATED | PF_TAG_REROUTE);
     437           0 :         else if (m->m_pkthdr.pf.flags & PF_TAG_REROUTE) {
     438             :                 /* tag as generated to skip over pf_test on rerun */
     439           0 :                 m->m_pkthdr.pf.flags |= PF_TAG_GENERATED;
     440             :                 ro = NULL;
     441           0 :                 if_put(ifp); /* drop reference since target changed */
     442             :                 ifp = NULL;
     443           0 :                 goto reroute;
     444             :         }
     445             : #endif
     446           0 :         in_proto_cksum_out(m, ifp);
     447             : 
     448             : #ifdef IPSEC
     449           0 :         if (ipsec_in_use && (flags & IP_FORWARDING) && (ipforwarding == 2) &&
     450           0 :             (m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL) == NULL)) {
     451           0 :                 error = EHOSTUNREACH;
     452           0 :                 m_freem(m);
     453           0 :                 goto done;
     454             :         }
     455             : #endif
     456             : 
     457             :         /*
     458             :          * If small enough for interface, can just send directly.
     459             :          */
     460           0 :         if (ntohs(ip->ip_len) <= mtu) {
     461           0 :                 ip->ip_sum = 0;
     462           0 :                 if ((ifp->if_capabilities & IFCAP_CSUM_IPv4) &&
     463           0 :                     (ifp->if_bridgeport == NULL))
     464           0 :                         m->m_pkthdr.csum_flags |= M_IPV4_CSUM_OUT;
     465             :                 else {
     466           0 :                         ipstat_inc(ips_outswcsum);
     467           0 :                         ip->ip_sum = in_cksum(m, hlen);
     468             :                 }
     469             : 
     470           0 :                 error = ifp->if_output(ifp, m, sintosa(dst), ro->ro_rt);
     471           0 :                 goto done;
     472             :         }
     473             : 
     474             :         /*
     475             :          * Too large for interface; fragment if possible.
     476             :          * Must be able to put at least 8 bytes per fragment.
     477             :          */
     478           0 :         if (ip->ip_off & htons(IP_DF)) {
     479             : #ifdef IPSEC
     480           0 :                 if (ip_mtudisc)
     481           0 :                         ipsec_adjust_mtu(m, ifp->if_mtu);
     482             : #endif
     483           0 :                 error = EMSGSIZE;
     484             :                 /*
     485             :                  * This case can happen if the user changed the MTU
     486             :                  * of an interface after enabling IP on it.  Because
     487             :                  * most netifs don't keep track of routes pointing to
     488             :                  * them, there is no way for one to update all its
     489             :                  * routes when the MTU is changed.
     490             :                  */
     491           0 :                 if (rtisvalid(ro->ro_rt) &&
     492           0 :                     ISSET(ro->ro_rt->rt_flags, RTF_HOST) &&
     493           0 :                     !(ro->ro_rt->rt_locks & RTV_MTU) &&
     494           0 :                     (ro->ro_rt->rt_mtu > ifp->if_mtu)) {
     495           0 :                         ro->ro_rt->rt_mtu = ifp->if_mtu;
     496           0 :                 }
     497           0 :                 ipstat_inc(ips_cantfrag);
     498           0 :                 goto bad;
     499             :         }
     500             : 
     501           0 :         error = ip_fragment(m, ifp, mtu);
     502           0 :         if (error) {
     503           0 :                 m = m0 = NULL;
     504           0 :                 goto bad;
     505             :         }
     506             : 
     507           0 :         for (; m; m = m0) {
     508           0 :                 m0 = m->m_nextpkt;
     509           0 :                 m->m_nextpkt = 0;
     510           0 :                 if (error == 0)
     511           0 :                         error = ifp->if_output(ifp, m, sintosa(dst), ro->ro_rt);
     512             :                 else
     513           0 :                         m_freem(m);
     514             :         }
     515             : 
     516           0 :         if (error == 0)
     517           0 :                 ipstat_inc(ips_fragmented);
     518             : 
     519             : done:
     520           0 :         if (ro == &iproute && ro->ro_rt)
     521           0 :                 rtfree(ro->ro_rt);
     522           0 :         if_put(ifp);
     523           0 :         return (error);
     524             : bad:
     525           0 :         m_freem(m0);
     526           0 :         goto done;
     527           0 : }
     528             : 
     529             : #ifdef IPSEC
     530             : struct tdb *
     531           0 : ip_output_ipsec_lookup(struct mbuf *m, int hlen, int *error, struct inpcb *inp,
     532             :     int ipsecflowinfo)
     533             : {
     534             :         struct m_tag *mtag;
     535             :         struct tdb_ident *tdbi;
     536             :         struct tdb *tdb;
     537             : 
     538             :         /* Do we have any pending SAs to apply ? */
     539           0 :         tdb = ipsp_spd_lookup(m, AF_INET, hlen, error, IPSP_DIRECTION_OUT,
     540             :             NULL, inp, ipsecflowinfo);
     541           0 :         if (tdb == NULL)
     542           0 :                 return NULL;
     543             :         /* Loop detection */
     544           0 :         for (mtag = m_tag_first(m); mtag != NULL; mtag = m_tag_next(m, mtag)) {
     545           0 :                 if (mtag->m_tag_id != PACKET_TAG_IPSEC_OUT_DONE)
     546             :                         continue;
     547           0 :                 tdbi = (struct tdb_ident *)(mtag + 1);
     548           0 :                 if (tdbi->spi == tdb->tdb_spi &&
     549           0 :                     tdbi->proto == tdb->tdb_sproto &&
     550           0 :                     tdbi->rdomain == tdb->tdb_rdomain &&
     551           0 :                     !memcmp(&tdbi->dst, &tdb->tdb_dst,
     552             :                     sizeof(union sockaddr_union))) {
     553             :                         /* no IPsec needed */
     554           0 :                         return NULL;
     555             :                 }
     556             :         }
     557           0 :         return tdb;
     558           0 : }
     559             : 
     560             : int
     561           0 : ip_output_ipsec_send(struct tdb *tdb, struct mbuf *m, struct route *ro, int fwd)
     562             : {
     563             : #if NPF > 0
     564             :         struct ifnet *encif;
     565             : #endif
     566             :         struct ip *ip;
     567             :         int error;
     568             : 
     569             : #if NPF > 0
     570             :         /*
     571             :          * Packet filter
     572             :          */
     573           0 :         if ((encif = enc_getif(tdb->tdb_rdomain, tdb->tdb_tap)) == NULL ||
     574           0 :             pf_test(AF_INET, fwd ? PF_FWD : PF_OUT, encif, &m) != PF_PASS) {
     575           0 :                 m_freem(m);
     576           0 :                 return EACCES;
     577             :         }
     578           0 :         if (m == NULL)
     579           0 :                 return 0;
     580             :         /*
     581             :          * PF_TAG_REROUTE handling or not...
     582             :          * Packet is entering IPsec so the routing is
     583             :          * already overruled by the IPsec policy.
     584             :          * Until now the change was not reconsidered.
     585             :          * What's the behaviour?
     586             :          */
     587           0 :         in_proto_cksum_out(m, encif);
     588             : #endif
     589             : 
     590             :         /* Check if we are allowed to fragment */
     591           0 :         ip = mtod(m, struct ip *);
     592           0 :         if (ip_mtudisc && (ip->ip_off & htons(IP_DF)) && tdb->tdb_mtu &&
     593           0 :             ntohs(ip->ip_len) > tdb->tdb_mtu &&
     594           0 :             tdb->tdb_mtutimeout > time_second) {
     595             :                 struct rtentry *rt = NULL;
     596             :                 int rt_mtucloned = 0;
     597             :                 int transportmode = 0;
     598             : 
     599           0 :                 transportmode = (tdb->tdb_dst.sa.sa_family == AF_INET) &&
     600           0 :                     (tdb->tdb_dst.sin.sin_addr.s_addr == ip->ip_dst.s_addr);
     601             : 
     602             :                 /* Find a host route to store the mtu in */
     603           0 :                 if (ro != NULL)
     604           0 :                         rt = ro->ro_rt;
     605             :                 /* but don't add a PMTU route for transport mode SAs */
     606           0 :                 if (transportmode)
     607           0 :                         rt = NULL;
     608           0 :                 else if (rt == NULL || (rt->rt_flags & RTF_HOST) == 0) {
     609           0 :                         rt = icmp_mtudisc_clone(ip->ip_dst,
     610           0 :                             m->m_pkthdr.ph_rtableid);
     611             :                         rt_mtucloned = 1;
     612           0 :                 }
     613             :                 DPRINTF(("%s: spi %08x mtu %d rt %p cloned %d\n", __func__,
     614             :                     ntohl(tdb->tdb_spi), tdb->tdb_mtu, rt, rt_mtucloned));
     615           0 :                 if (rt != NULL) {
     616           0 :                         rt->rt_mtu = tdb->tdb_mtu;
     617           0 :                         if (ro && ro->ro_rt != NULL) {
     618           0 :                                 rtfree(ro->ro_rt);
     619           0 :                                 ro->ro_rt = rtalloc(&ro->ro_dst, RT_RESOLVE,
     620           0 :                                     m->m_pkthdr.ph_rtableid);
     621           0 :                         }
     622           0 :                         if (rt_mtucloned)
     623           0 :                                 rtfree(rt);
     624             :                 }
     625           0 :                 ipsec_adjust_mtu(m, tdb->tdb_mtu);
     626           0 :                 m_freem(m);
     627             :                 return EMSGSIZE;
     628             :         }
     629             : 
     630             :         /*
     631             :          * Clear these -- they'll be set in the recursive invocation
     632             :          * as needed.
     633             :          */
     634           0 :         m->m_flags &= ~(M_MCAST | M_BCAST);
     635             : 
     636             :         /* Callee frees mbuf */
     637           0 :         error = ipsp_process_packet(m, tdb, AF_INET, 0);
     638           0 :         if (error) {
     639           0 :                 ipsecstat_inc(ipsec_odrops);
     640           0 :                 tdb->tdb_odrops++;
     641           0 :         }
     642           0 :         return error;
     643           0 : }
     644             : #endif /* IPSEC */
     645             : 
     646             : int
     647           0 : ip_fragment(struct mbuf *m, struct ifnet *ifp, u_long mtu)
     648             : {
     649             :         struct ip *ip, *mhip;
     650             :         struct mbuf *m0;
     651             :         int len, hlen, off;
     652             :         int mhlen, firstlen;
     653             :         struct mbuf **mnext;
     654             :         int fragments = 0;
     655             :         int error = 0;
     656             : 
     657           0 :         ip = mtod(m, struct ip *);
     658           0 :         hlen = ip->ip_hl << 2;
     659             : 
     660           0 :         len = (mtu - hlen) &~ 7;
     661           0 :         if (len < 8) {
     662           0 :                 m_freem(m);
     663           0 :                 return (EMSGSIZE);
     664             :         }
     665             : 
     666             :         /*
     667             :          * If we are doing fragmentation, we can't defer TCP/UDP
     668             :          * checksumming; compute the checksum and clear the flag.
     669             :          */
     670           0 :         in_proto_cksum_out(m, NULL);
     671             :         firstlen = len;
     672           0 :         mnext = &m->m_nextpkt;
     673             : 
     674             :         /*
     675             :          * Loop through length of segment after first fragment,
     676             :          * make new header and copy data of each part and link onto chain.
     677             :          */
     678             :         m0 = m;
     679             :         mhlen = sizeof (struct ip);
     680           0 :         for (off = hlen + len; off < ntohs(ip->ip_len); off += len) {
     681           0 :                 MGETHDR(m, M_DONTWAIT, MT_HEADER);
     682           0 :                 if (m == NULL) {
     683           0 :                         ipstat_inc(ips_odropped);
     684             :                         error = ENOBUFS;
     685           0 :                         goto sendorfree;
     686             :                 }
     687           0 :                 *mnext = m;
     688           0 :                 mnext = &m->m_nextpkt;
     689           0 :                 m->m_data += max_linkhdr;
     690           0 :                 mhip = mtod(m, struct ip *);
     691           0 :                 *mhip = *ip;
     692             :                 /* we must inherit MCAST/BCAST flags, routing table and prio */
     693           0 :                 m->m_flags |= m0->m_flags & (M_MCAST|M_BCAST);
     694           0 :                 m->m_pkthdr.ph_rtableid = m0->m_pkthdr.ph_rtableid;
     695           0 :                 m->m_pkthdr.pf.prio = m0->m_pkthdr.pf.prio;
     696           0 :                 if (hlen > sizeof (struct ip)) {
     697           0 :                         mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip);
     698           0 :                         mhip->ip_hl = mhlen >> 2;
     699           0 :                 }
     700           0 :                 m->m_len = mhlen;
     701           0 :                 mhip->ip_off = ((off - hlen) >> 3) +
     702           0 :                     (ntohs(ip->ip_off) & ~IP_MF);
     703           0 :                 if (ip->ip_off & htons(IP_MF))
     704           0 :                         mhip->ip_off |= IP_MF;
     705           0 :                 if (off + len >= ntohs(ip->ip_len))
     706           0 :                         len = ntohs(ip->ip_len) - off;
     707             :                 else
     708           0 :                         mhip->ip_off |= IP_MF;
     709           0 :                 mhip->ip_len = htons((u_int16_t)(len + mhlen));
     710           0 :                 m->m_next = m_copym(m0, off, len, M_NOWAIT);
     711           0 :                 if (m->m_next == 0) {
     712           0 :                         ipstat_inc(ips_odropped);
     713             :                         error = ENOBUFS;
     714           0 :                         goto sendorfree;
     715             :                 }
     716           0 :                 m->m_pkthdr.len = mhlen + len;
     717           0 :                 m->m_pkthdr.ph_ifidx = 0;
     718           0 :                 mhip->ip_off = htons((u_int16_t)mhip->ip_off);
     719           0 :                 mhip->ip_sum = 0;
     720           0 :                 if ((ifp != NULL) &&
     721           0 :                     (ifp->if_capabilities & IFCAP_CSUM_IPv4) &&
     722           0 :                     (ifp->if_bridgeport == NULL))
     723           0 :                         m->m_pkthdr.csum_flags |= M_IPV4_CSUM_OUT;
     724             :                 else {
     725           0 :                         ipstat_inc(ips_outswcsum);
     726           0 :                         mhip->ip_sum = in_cksum(m, mhlen);
     727             :                 }
     728           0 :                 ipstat_inc(ips_ofragments);
     729           0 :                 fragments++;
     730             :         }
     731             :         /*
     732             :          * Update first fragment by trimming what's been copied out
     733             :          * and updating header, then send each fragment (in order).
     734             :          */
     735             :         m = m0;
     736           0 :         m_adj(m, hlen + firstlen - ntohs(ip->ip_len));
     737           0 :         m->m_pkthdr.len = hlen + firstlen;
     738           0 :         ip->ip_len = htons((u_int16_t)m->m_pkthdr.len);
     739           0 :         ip->ip_off |= htons(IP_MF);
     740           0 :         ip->ip_sum = 0;
     741           0 :         if ((ifp != NULL) &&
     742           0 :             (ifp->if_capabilities & IFCAP_CSUM_IPv4) &&
     743           0 :             (ifp->if_bridgeport == NULL))
     744           0 :                 m->m_pkthdr.csum_flags |= M_IPV4_CSUM_OUT;
     745             :         else {
     746           0 :                 ipstat_inc(ips_outswcsum);
     747           0 :                 ip->ip_sum = in_cksum(m, hlen);
     748             :         }
     749             : sendorfree:
     750           0 :         if (error) {
     751           0 :                 for (m = m0; m; m = m0) {
     752           0 :                         m0 = m->m_nextpkt;
     753           0 :                         m->m_nextpkt = NULL;
     754           0 :                         m_freem(m);
     755             :                 }
     756             :         }
     757             : 
     758           0 :         return (error);
     759           0 : }
     760             : 
     761             : /*
     762             :  * Insert IP options into preformed packet.
     763             :  * Adjust IP destination as required for IP source routing,
     764             :  * as indicated by a non-zero in_addr at the start of the options.
     765             :  */
     766             : struct mbuf *
     767           0 : ip_insertoptions(struct mbuf *m, struct mbuf *opt, int *phlen)
     768             : {
     769           0 :         struct ipoption *p = mtod(opt, struct ipoption *);
     770             :         struct mbuf *n;
     771           0 :         struct ip *ip = mtod(m, struct ip *);
     772             :         unsigned int optlen;
     773             : 
     774           0 :         optlen = opt->m_len - sizeof(p->ipopt_dst);
     775           0 :         if (optlen + ntohs(ip->ip_len) > IP_MAXPACKET)
     776           0 :                 return (m);             /* XXX should fail */
     777           0 :         if (p->ipopt_dst.s_addr)
     778           0 :                 ip->ip_dst = p->ipopt_dst;
     779           0 :         if (m->m_flags & M_EXT || m->m_data - optlen < m->m_pktdat) {
     780           0 :                 MGETHDR(n, M_DONTWAIT, MT_HEADER);
     781           0 :                 if (n == NULL)
     782           0 :                         return (m);
     783           0 :                 M_MOVE_HDR(n, m);
     784           0 :                 n->m_pkthdr.len += optlen;
     785           0 :                 m->m_len -= sizeof(struct ip);
     786           0 :                 m->m_data += sizeof(struct ip);
     787           0 :                 n->m_next = m;
     788             :                 m = n;
     789           0 :                 m->m_len = optlen + sizeof(struct ip);
     790           0 :                 m->m_data += max_linkhdr;
     791           0 :                 memcpy(mtod(m, caddr_t), ip, sizeof(struct ip));
     792           0 :         } else {
     793           0 :                 m->m_data -= optlen;
     794           0 :                 m->m_len += optlen;
     795           0 :                 m->m_pkthdr.len += optlen;
     796           0 :                 memmove(mtod(m, caddr_t), (caddr_t)ip, sizeof(struct ip));
     797             :         }
     798           0 :         ip = mtod(m, struct ip *);
     799           0 :         memcpy(ip + 1, p->ipopt_list, optlen);
     800           0 :         *phlen = sizeof(struct ip) + optlen;
     801           0 :         ip->ip_len = htons(ntohs(ip->ip_len) + optlen);
     802           0 :         return (m);
     803           0 : }
     804             : 
     805             : /*
     806             :  * Copy options from ip to jp,
     807             :  * omitting those not copied during fragmentation.
     808             :  */
     809             : int
     810           0 : ip_optcopy(struct ip *ip, struct ip *jp)
     811             : {
     812             :         u_char *cp, *dp;
     813             :         int opt, optlen, cnt;
     814             : 
     815           0 :         cp = (u_char *)(ip + 1);
     816           0 :         dp = (u_char *)(jp + 1);
     817           0 :         cnt = (ip->ip_hl << 2) - sizeof (struct ip);
     818           0 :         for (; cnt > 0; cnt -= optlen, cp += optlen) {
     819           0 :                 opt = cp[0];
     820           0 :                 if (opt == IPOPT_EOL)
     821             :                         break;
     822           0 :                 if (opt == IPOPT_NOP) {
     823             :                         /* Preserve for IP mcast tunnel's LSRR alignment. */
     824           0 :                         *dp++ = IPOPT_NOP;
     825             :                         optlen = 1;
     826           0 :                         continue;
     827             :                 }
     828             : #ifdef DIAGNOSTIC
     829           0 :                 if (cnt < IPOPT_OLEN + sizeof(*cp))
     830           0 :                         panic("malformed IPv4 option passed to ip_optcopy");
     831             : #endif
     832           0 :                 optlen = cp[IPOPT_OLEN];
     833             : #ifdef DIAGNOSTIC
     834           0 :                 if (optlen < IPOPT_OLEN + sizeof(*cp) || optlen > cnt)
     835           0 :                         panic("malformed IPv4 option passed to ip_optcopy");
     836             : #endif
     837             :                 /* bogus lengths should have been caught by ip_dooptions */
     838           0 :                 if (optlen > cnt)
     839           0 :                         optlen = cnt;
     840           0 :                 if (IPOPT_COPIED(opt)) {
     841           0 :                         memcpy(dp, cp, optlen);
     842           0 :                         dp += optlen;
     843           0 :                 }
     844             :         }
     845           0 :         for (optlen = dp - (u_char *)(jp+1); optlen & 0x3; optlen++)
     846           0 :                 *dp++ = IPOPT_EOL;
     847           0 :         return (optlen);
     848             : }
     849             : 
     850             : /*
     851             :  * IP socket option processing.
     852             :  */
     853             : int
     854           0 : ip_ctloutput(int op, struct socket *so, int level, int optname,
     855             :     struct mbuf *m)
     856             : {
     857           0 :         struct inpcb *inp = sotoinpcb(so);
     858             :         int optval = 0;
     859           0 :         struct proc *p = curproc; /* XXX */
     860             :         int error = 0;
     861             :         u_int rtid = 0;
     862             : 
     863           0 :         if (level != IPPROTO_IP) {
     864             :                 error = EINVAL;
     865           0 :         } else switch (op) {
     866             :         case PRCO_SETOPT:
     867           0 :                 switch (optname) {
     868             :                 case IP_OPTIONS:
     869           0 :                         return (ip_pcbopts(&inp->inp_options, m));
     870             : 
     871             :                 case IP_TOS:
     872             :                 case IP_TTL:
     873             :                 case IP_MINTTL:
     874             :                 case IP_RECVOPTS:
     875             :                 case IP_RECVRETOPTS:
     876             :                 case IP_RECVDSTADDR:
     877             :                 case IP_RECVIF:
     878             :                 case IP_RECVTTL:
     879             :                 case IP_RECVDSTPORT:
     880             :                 case IP_RECVRTABLE:
     881             :                 case IP_IPSECFLOWINFO:
     882           0 :                         if (m == NULL || m->m_len != sizeof(int))
     883           0 :                                 error = EINVAL;
     884             :                         else {
     885           0 :                                 optval = *mtod(m, int *);
     886           0 :                                 switch (optname) {
     887             : 
     888             :                                 case IP_TOS:
     889           0 :                                         inp->inp_ip.ip_tos = optval;
     890           0 :                                         break;
     891             : 
     892             :                                 case IP_TTL:
     893           0 :                                         if (optval > 0 && optval <= MAXTTL)
     894           0 :                                                 inp->inp_ip.ip_ttl = optval;
     895           0 :                                         else if (optval == -1)
     896           0 :                                                 inp->inp_ip.ip_ttl = ip_defttl;
     897             :                                         else
     898             :                                                 error = EINVAL;
     899             :                                         break;
     900             : 
     901             :                                 case IP_MINTTL:
     902           0 :                                         if (optval >= 0 && optval <= MAXTTL)
     903           0 :                                                 inp->inp_ip_minttl = optval;
     904             :                                         else
     905             :                                                 error = EINVAL;
     906             :                                         break;
     907             : #define OPTSET(bit) \
     908             :         if (optval) \
     909             :                 inp->inp_flags |= bit; \
     910             :         else \
     911             :                 inp->inp_flags &= ~bit;
     912             : 
     913             :                                 case IP_RECVOPTS:
     914           0 :                                         OPTSET(INP_RECVOPTS);
     915             :                                         break;
     916             : 
     917             :                                 case IP_RECVRETOPTS:
     918           0 :                                         OPTSET(INP_RECVRETOPTS);
     919             :                                         break;
     920             : 
     921             :                                 case IP_RECVDSTADDR:
     922           0 :                                         OPTSET(INP_RECVDSTADDR);
     923             :                                         break;
     924             :                                 case IP_RECVIF:
     925           0 :                                         OPTSET(INP_RECVIF);
     926             :                                         break;
     927             :                                 case IP_RECVTTL:
     928           0 :                                         OPTSET(INP_RECVTTL);
     929             :                                         break;
     930             :                                 case IP_RECVDSTPORT:
     931           0 :                                         OPTSET(INP_RECVDSTPORT);
     932             :                                         break;
     933             :                                 case IP_RECVRTABLE:
     934           0 :                                         OPTSET(INP_RECVRTABLE);
     935             :                                         break;
     936             :                                 case IP_IPSECFLOWINFO:
     937           0 :                                         OPTSET(INP_IPSECFLOWINFO);
     938             :                                         break;
     939             :                                 }
     940             :                         }
     941             :                         break;
     942             : #undef OPTSET
     943             : 
     944             :                 case IP_MULTICAST_IF:
     945             :                 case IP_MULTICAST_TTL:
     946             :                 case IP_MULTICAST_LOOP:
     947             :                 case IP_ADD_MEMBERSHIP:
     948             :                 case IP_DROP_MEMBERSHIP:
     949           0 :                         error = ip_setmoptions(optname, &inp->inp_moptions, m,
     950           0 :                             inp->inp_rtableid);
     951           0 :                         break;
     952             : 
     953             :                 case IP_PORTRANGE:
     954           0 :                         if (m == NULL || m->m_len != sizeof(int))
     955           0 :                                 error = EINVAL;
     956             :                         else {
     957           0 :                                 optval = *mtod(m, int *);
     958             : 
     959           0 :                                 switch (optval) {
     960             : 
     961             :                                 case IP_PORTRANGE_DEFAULT:
     962           0 :                                         inp->inp_flags &= ~(INP_LOWPORT);
     963           0 :                                         inp->inp_flags &= ~(INP_HIGHPORT);
     964           0 :                                         break;
     965             : 
     966             :                                 case IP_PORTRANGE_HIGH:
     967           0 :                                         inp->inp_flags &= ~(INP_LOWPORT);
     968           0 :                                         inp->inp_flags |= INP_HIGHPORT;
     969           0 :                                         break;
     970             : 
     971             :                                 case IP_PORTRANGE_LOW:
     972           0 :                                         inp->inp_flags &= ~(INP_HIGHPORT);
     973           0 :                                         inp->inp_flags |= INP_LOWPORT;
     974           0 :                                         break;
     975             : 
     976             :                                 default:
     977             : 
     978             :                                         error = EINVAL;
     979           0 :                                         break;
     980             :                                 }
     981             :                         }
     982             :                         break;
     983             :                 case IP_AUTH_LEVEL:
     984             :                 case IP_ESP_TRANS_LEVEL:
     985             :                 case IP_ESP_NETWORK_LEVEL:
     986             :                 case IP_IPCOMP_LEVEL:
     987             : #ifndef IPSEC
     988             :                         error = EOPNOTSUPP;
     989             : #else
     990           0 :                         if (m == NULL || m->m_len != sizeof(int)) {
     991             :                                 error = EINVAL;
     992           0 :                                 break;
     993             :                         }
     994           0 :                         optval = *mtod(m, int *);
     995             : 
     996           0 :                         if (optval < IPSEC_LEVEL_BYPASS ||
     997           0 :                             optval > IPSEC_LEVEL_UNIQUE) {
     998             :                                 error = EINVAL;
     999           0 :                                 break;
    1000             :                         }
    1001             : 
    1002           0 :                         switch (optname) {
    1003             :                         case IP_AUTH_LEVEL:
    1004           0 :                                 if (optval < IPSEC_AUTH_LEVEL_DEFAULT &&
    1005           0 :                                     suser(p)) {
    1006             :                                         error = EACCES;
    1007           0 :                                         break;
    1008             :                                 }
    1009           0 :                                 inp->inp_seclevel[SL_AUTH] = optval;
    1010           0 :                                 break;
    1011             : 
    1012             :                         case IP_ESP_TRANS_LEVEL:
    1013           0 :                                 if (optval < IPSEC_ESP_TRANS_LEVEL_DEFAULT &&
    1014           0 :                                     suser(p)) {
    1015             :                                         error = EACCES;
    1016           0 :                                         break;
    1017             :                                 }
    1018           0 :                                 inp->inp_seclevel[SL_ESP_TRANS] = optval;
    1019           0 :                                 break;
    1020             : 
    1021             :                         case IP_ESP_NETWORK_LEVEL:
    1022           0 :                                 if (optval < IPSEC_ESP_NETWORK_LEVEL_DEFAULT &&
    1023           0 :                                     suser(p)) {
    1024             :                                         error = EACCES;
    1025           0 :                                         break;
    1026             :                                 }
    1027           0 :                                 inp->inp_seclevel[SL_ESP_NETWORK] = optval;
    1028           0 :                                 break;
    1029             :                         case IP_IPCOMP_LEVEL:
    1030           0 :                                 if (optval < IPSEC_IPCOMP_LEVEL_DEFAULT &&
    1031           0 :                                     suser(p)) {
    1032             :                                         error = EACCES;
    1033           0 :                                         break;
    1034             :                                 }
    1035           0 :                                 inp->inp_seclevel[SL_IPCOMP] = optval;
    1036           0 :                                 break;
    1037             :                         }
    1038             : #endif
    1039             :                         break;
    1040             : 
    1041             :                 case IP_IPSEC_LOCAL_ID:
    1042             :                 case IP_IPSEC_REMOTE_ID:
    1043             :                         error = EOPNOTSUPP;
    1044           0 :                         break;
    1045             :                 case SO_RTABLE:
    1046           0 :                         if (m == NULL || m->m_len < sizeof(u_int)) {
    1047             :                                 error = EINVAL;
    1048           0 :                                 break;
    1049             :                         }
    1050           0 :                         rtid = *mtod(m, u_int *);
    1051           0 :                         if (inp->inp_rtableid == rtid)
    1052             :                                 break;
    1053             :                         /* needs privileges to switch when already set */
    1054           0 :                         if (p->p_p->ps_rtableid != rtid &&
    1055           0 :                             p->p_p->ps_rtableid != 0 &&
    1056           0 :                             (error = suser(p)) != 0)
    1057             :                                 break;
    1058             :                         /* table must exist */
    1059           0 :                         if (!rtable_exists(rtid)) {
    1060             :                                 error = EINVAL;
    1061           0 :                                 break;
    1062             :                         }
    1063           0 :                         if (inp->inp_lport) {
    1064             :                                 error = EBUSY;
    1065           0 :                                 break;
    1066             :                         }
    1067           0 :                         inp->inp_rtableid = rtid;
    1068           0 :                         in_pcbrehash(inp);
    1069           0 :                         break;
    1070             :                 case IP_PIPEX:
    1071           0 :                         if (m != NULL && m->m_len == sizeof(int))
    1072           0 :                                 inp->inp_pipex = *mtod(m, int *);
    1073             :                         else
    1074             :                                 error = EINVAL;
    1075             :                         break;
    1076             : 
    1077             :                 default:
    1078             :                         error = ENOPROTOOPT;
    1079           0 :                         break;
    1080             :                 }
    1081             :                 break;
    1082             : 
    1083             :         case PRCO_GETOPT:
    1084           0 :                 switch (optname) {
    1085             :                 case IP_OPTIONS:
    1086             :                 case IP_RETOPTS:
    1087           0 :                         if (inp->inp_options) {
    1088           0 :                                 m->m_len = inp->inp_options->m_len;
    1089           0 :                                 memcpy(mtod(m, caddr_t),
    1090             :                                     mtod(inp->inp_options, caddr_t), m->m_len);
    1091           0 :                         } else
    1092           0 :                                 m->m_len = 0;
    1093             :                         break;
    1094             : 
    1095             :                 case IP_TOS:
    1096             :                 case IP_TTL:
    1097             :                 case IP_MINTTL:
    1098             :                 case IP_RECVOPTS:
    1099             :                 case IP_RECVRETOPTS:
    1100             :                 case IP_RECVDSTADDR:
    1101             :                 case IP_RECVIF:
    1102             :                 case IP_RECVTTL:
    1103             :                 case IP_RECVDSTPORT:
    1104             :                 case IP_RECVRTABLE:
    1105             :                 case IP_IPSECFLOWINFO:
    1106             :                 case IP_IPDEFTTL:
    1107           0 :                         m->m_len = sizeof(int);
    1108           0 :                         switch (optname) {
    1109             : 
    1110             :                         case IP_TOS:
    1111           0 :                                 optval = inp->inp_ip.ip_tos;
    1112           0 :                                 break;
    1113             : 
    1114             :                         case IP_TTL:
    1115           0 :                                 optval = inp->inp_ip.ip_ttl;
    1116           0 :                                 break;
    1117             : 
    1118             :                         case IP_MINTTL:
    1119           0 :                                 optval = inp->inp_ip_minttl;
    1120           0 :                                 break;
    1121             : 
    1122             :                         case IP_IPDEFTTL:
    1123           0 :                                 optval = ip_defttl;
    1124           0 :                                 break;
    1125             : 
    1126             : #define OPTBIT(bit)     (inp->inp_flags & bit ? 1 : 0)
    1127             : 
    1128             :                         case IP_RECVOPTS:
    1129           0 :                                 optval = OPTBIT(INP_RECVOPTS);
    1130           0 :                                 break;
    1131             : 
    1132             :                         case IP_RECVRETOPTS:
    1133           0 :                                 optval = OPTBIT(INP_RECVRETOPTS);
    1134           0 :                                 break;
    1135             : 
    1136             :                         case IP_RECVDSTADDR:
    1137           0 :                                 optval = OPTBIT(INP_RECVDSTADDR);
    1138           0 :                                 break;
    1139             :                         case IP_RECVIF:
    1140           0 :                                 optval = OPTBIT(INP_RECVIF);
    1141           0 :                                 break;
    1142             :                         case IP_RECVTTL:
    1143           0 :                                 optval = OPTBIT(INP_RECVTTL);
    1144           0 :                                 break;
    1145             :                         case IP_RECVDSTPORT:
    1146           0 :                                 optval = OPTBIT(INP_RECVDSTPORT);
    1147           0 :                                 break;
    1148             :                         case IP_RECVRTABLE:
    1149           0 :                                 optval = OPTBIT(INP_RECVRTABLE);
    1150           0 :                                 break;
    1151             :                         case IP_IPSECFLOWINFO:
    1152           0 :                                 optval = OPTBIT(INP_IPSECFLOWINFO);
    1153           0 :                                 break;
    1154             :                         }
    1155           0 :                         *mtod(m, int *) = optval;
    1156           0 :                         break;
    1157             : 
    1158             :                 case IP_MULTICAST_IF:
    1159             :                 case IP_MULTICAST_TTL:
    1160             :                 case IP_MULTICAST_LOOP:
    1161             :                 case IP_ADD_MEMBERSHIP:
    1162             :                 case IP_DROP_MEMBERSHIP:
    1163           0 :                         error = ip_getmoptions(optname, inp->inp_moptions, m);
    1164           0 :                         break;
    1165             : 
    1166             :                 case IP_PORTRANGE:
    1167           0 :                         m->m_len = sizeof(int);
    1168             : 
    1169           0 :                         if (inp->inp_flags & INP_HIGHPORT)
    1170           0 :                                 optval = IP_PORTRANGE_HIGH;
    1171           0 :                         else if (inp->inp_flags & INP_LOWPORT)
    1172           0 :                                 optval = IP_PORTRANGE_LOW;
    1173             :                         else
    1174             :                                 optval = 0;
    1175             : 
    1176           0 :                         *mtod(m, int *) = optval;
    1177           0 :                         break;
    1178             : 
    1179             :                 case IP_AUTH_LEVEL:
    1180             :                 case IP_ESP_TRANS_LEVEL:
    1181             :                 case IP_ESP_NETWORK_LEVEL:
    1182             :                 case IP_IPCOMP_LEVEL:
    1183             : #ifndef IPSEC
    1184             :                         m->m_len = sizeof(int);
    1185             :                         *mtod(m, int *) = IPSEC_LEVEL_NONE;
    1186             : #else
    1187           0 :                         m->m_len = sizeof(int);
    1188           0 :                         switch (optname) {
    1189             :                         case IP_AUTH_LEVEL:
    1190           0 :                                 optval = inp->inp_seclevel[SL_AUTH];
    1191           0 :                                 break;
    1192             : 
    1193             :                         case IP_ESP_TRANS_LEVEL:
    1194           0 :                                 optval = inp->inp_seclevel[SL_ESP_TRANS];
    1195           0 :                                 break;
    1196             : 
    1197             :                         case IP_ESP_NETWORK_LEVEL:
    1198           0 :                                 optval = inp->inp_seclevel[SL_ESP_NETWORK];
    1199           0 :                                 break;
    1200             :                         case IP_IPCOMP_LEVEL:
    1201           0 :                                 optval = inp->inp_seclevel[SL_IPCOMP];
    1202           0 :                                 break;
    1203             :                         }
    1204           0 :                         *mtod(m, int *) = optval;
    1205             : #endif
    1206           0 :                         break;
    1207             :                 case IP_IPSEC_LOCAL_ID:
    1208             :                 case IP_IPSEC_REMOTE_ID:
    1209             :                         error = EOPNOTSUPP;
    1210           0 :                         break;
    1211             :                 case SO_RTABLE:
    1212           0 :                         m->m_len = sizeof(u_int);
    1213           0 :                         *mtod(m, u_int *) = inp->inp_rtableid;
    1214           0 :                         break;
    1215             :                 case IP_PIPEX:
    1216           0 :                         m->m_len = sizeof(int);
    1217           0 :                         *mtod(m, int *) = inp->inp_pipex;
    1218           0 :                         break;
    1219             :                 default:
    1220             :                         error = ENOPROTOOPT;
    1221           0 :                         break;
    1222             :                 }
    1223             :                 break;
    1224             :         }
    1225           0 :         return (error);
    1226           0 : }
    1227             : 
    1228             : /*
    1229             :  * Set up IP options in pcb for insertion in output packets.
    1230             :  * Store in mbuf with pointer in pcbopt, adding pseudo-option
    1231             :  * with destination address if source routed.
    1232             :  */
    1233             : int
    1234           0 : ip_pcbopts(struct mbuf **pcbopt, struct mbuf *m)
    1235             : {
    1236             :         int cnt, optlen;
    1237             :         u_char *cp;
    1238             :         u_char opt;
    1239             : 
    1240             :         /* turn off any old options */
    1241           0 :         m_free(*pcbopt);
    1242           0 :         *pcbopt = 0;
    1243           0 :         if (m == NULL || m->m_len == 0) {
    1244             :                 /*
    1245             :                  * Only turning off any previous options.
    1246             :                  */
    1247           0 :                 return (0);
    1248             :         }
    1249             : 
    1250           0 :         if (m->m_len % sizeof(int32_t))
    1251           0 :                 return (EINVAL);
    1252             : 
    1253             :         /*
    1254             :          * IP first-hop destination address will be stored before
    1255             :          * actual options; move other options back
    1256             :          * and clear it when none present.
    1257             :          */
    1258           0 :         if (m->m_data + m->m_len + sizeof(struct in_addr) >= &m->m_dat[MLEN])
    1259           0 :                 return (EINVAL);
    1260             :         cnt = m->m_len;
    1261           0 :         m->m_len += sizeof(struct in_addr);
    1262           0 :         cp = mtod(m, u_char *) + sizeof(struct in_addr);
    1263           0 :         memmove((caddr_t)cp, mtod(m, caddr_t), (unsigned)cnt);
    1264           0 :         memset(mtod(m, caddr_t), 0, sizeof(struct in_addr));
    1265             : 
    1266           0 :         for (; cnt > 0; cnt -= optlen, cp += optlen) {
    1267           0 :                 opt = cp[IPOPT_OPTVAL];
    1268           0 :                 if (opt == IPOPT_EOL)
    1269             :                         break;
    1270           0 :                 if (opt == IPOPT_NOP)
    1271           0 :                         optlen = 1;
    1272             :                 else {
    1273           0 :                         if (cnt < IPOPT_OLEN + sizeof(*cp))
    1274           0 :                                 return (EINVAL);
    1275           0 :                         optlen = cp[IPOPT_OLEN];
    1276           0 :                         if (optlen < IPOPT_OLEN  + sizeof(*cp) || optlen > cnt)
    1277           0 :                                 return (EINVAL);
    1278             :                 }
    1279           0 :                 switch (opt) {
    1280             : 
    1281             :                 default:
    1282             :                         break;
    1283             : 
    1284             :                 case IPOPT_LSRR:
    1285             :                 case IPOPT_SSRR:
    1286             :                         /*
    1287             :                          * user process specifies route as:
    1288             :                          *      ->A->B->C->D
    1289             :                          * D must be our final destination (but we can't
    1290             :                          * check that since we may not have connected yet).
    1291             :                          * A is first hop destination, which doesn't appear in
    1292             :                          * actual IP option, but is stored before the options.
    1293             :                          */
    1294           0 :                         if (optlen < IPOPT_MINOFF - 1 + sizeof(struct in_addr))
    1295           0 :                                 return (EINVAL);
    1296           0 :                         m->m_len -= sizeof(struct in_addr);
    1297           0 :                         cnt -= sizeof(struct in_addr);
    1298           0 :                         optlen -= sizeof(struct in_addr);
    1299           0 :                         cp[IPOPT_OLEN] = optlen;
    1300             :                         /*
    1301             :                          * Move first hop before start of options.
    1302             :                          */
    1303           0 :                         memcpy(mtod(m, caddr_t), &cp[IPOPT_OFFSET+1],
    1304             :                             sizeof(struct in_addr));
    1305             :                         /*
    1306             :                          * Then copy rest of options back
    1307             :                          * to close up the deleted entry.
    1308             :                          */
    1309           0 :                         memmove((caddr_t)&cp[IPOPT_OFFSET+1],
    1310             :                             (caddr_t)(&cp[IPOPT_OFFSET+1] +
    1311             :                             sizeof(struct in_addr)),
    1312             :                             (unsigned)cnt - (IPOPT_OFFSET+1));
    1313           0 :                         break;
    1314             :                 }
    1315             :         }
    1316           0 :         if (m->m_len > MAX_IPOPTLEN + sizeof(struct in_addr))
    1317           0 :                 return (EINVAL);
    1318           0 :         *pcbopt = m_copym(m, 0, M_COPYALL, M_NOWAIT);
    1319           0 :         if (*pcbopt == NULL)
    1320           0 :                 return (ENOBUFS);
    1321             : 
    1322           0 :         return (0);
    1323           0 : }
    1324             : 
    1325             : /*
    1326             :  * Set the IP multicast options in response to user setsockopt().
    1327             :  */
    1328             : int
    1329           0 : ip_setmoptions(int optname, struct ip_moptions **imop, struct mbuf *m,
    1330             :     u_int rtableid)
    1331             : {
    1332             :         struct in_addr addr;
    1333             :         struct in_ifaddr *ia;
    1334             :         struct ip_mreq *mreq;
    1335             :         struct ifnet *ifp = NULL;
    1336           0 :         struct ip_moptions *imo = *imop;
    1337             :         struct in_multi **immp;
    1338             :         struct rtentry *rt;
    1339           0 :         struct sockaddr_in sin;
    1340             :         int i, error = 0;
    1341             :         u_char loop;
    1342             : 
    1343           0 :         if (imo == NULL) {
    1344             :                 /*
    1345             :                  * No multicast option buffer attached to the pcb;
    1346             :                  * allocate one and initialize to default values.
    1347             :                  */
    1348           0 :                 imo = malloc(sizeof(*imo), M_IPMOPTS, M_WAITOK|M_ZERO);
    1349           0 :                 immp = (struct in_multi **)malloc(
    1350             :                     (sizeof(*immp) * IP_MIN_MEMBERSHIPS), M_IPMOPTS,
    1351             :                     M_WAITOK|M_ZERO);
    1352           0 :                 *imop = imo;
    1353           0 :                 imo->imo_ifidx = 0;
    1354           0 :                 imo->imo_ttl = IP_DEFAULT_MULTICAST_TTL;
    1355           0 :                 imo->imo_loop = IP_DEFAULT_MULTICAST_LOOP;
    1356           0 :                 imo->imo_num_memberships = 0;
    1357           0 :                 imo->imo_max_memberships = IP_MIN_MEMBERSHIPS;
    1358           0 :                 imo->imo_membership = immp;
    1359           0 :         }
    1360             : 
    1361           0 :         switch (optname) {
    1362             : 
    1363             :         case IP_MULTICAST_IF:
    1364             :                 /*
    1365             :                  * Select the interface for outgoing multicast packets.
    1366             :                  */
    1367           0 :                 if (m == NULL || m->m_len != sizeof(struct in_addr)) {
    1368             :                         error = EINVAL;
    1369           0 :                         break;
    1370             :                 }
    1371           0 :                 addr = *(mtod(m, struct in_addr *));
    1372             :                 /*
    1373             :                  * INADDR_ANY is used to remove a previous selection.
    1374             :                  * When no interface is selected, a default one is
    1375             :                  * chosen every time a multicast packet is sent.
    1376             :                  */
    1377           0 :                 if (addr.s_addr == INADDR_ANY) {
    1378           0 :                         imo->imo_ifidx = 0;
    1379           0 :                         break;
    1380             :                 }
    1381             :                 /*
    1382             :                  * The selected interface is identified by its local
    1383             :                  * IP address.  Find the interface and confirm that
    1384             :                  * it supports multicasting.
    1385             :                  */
    1386           0 :                 memset(&sin, 0, sizeof(sin));
    1387           0 :                 sin.sin_len = sizeof(sin);
    1388           0 :                 sin.sin_family = AF_INET;
    1389           0 :                 sin.sin_addr = addr;
    1390           0 :                 ia = ifatoia(ifa_ifwithaddr(sintosa(&sin), rtableid));
    1391           0 :                 if (ia == NULL ||
    1392           0 :                     (ia->ia_ifp->if_flags & IFF_MULTICAST) == 0) {
    1393             :                         error = EADDRNOTAVAIL;
    1394           0 :                         break;
    1395             :                 }
    1396           0 :                 imo->imo_ifidx = ia->ia_ifp->if_index;
    1397           0 :                 break;
    1398             : 
    1399             :         case IP_MULTICAST_TTL:
    1400             :                 /*
    1401             :                  * Set the IP time-to-live for outgoing multicast packets.
    1402             :                  */
    1403           0 :                 if (m == NULL || m->m_len != 1) {
    1404             :                         error = EINVAL;
    1405           0 :                         break;
    1406             :                 }
    1407           0 :                 imo->imo_ttl = *(mtod(m, u_char *));
    1408           0 :                 break;
    1409             : 
    1410             :         case IP_MULTICAST_LOOP:
    1411             :                 /*
    1412             :                  * Set the loopback flag for outgoing multicast packets.
    1413             :                  * Must be zero or one.
    1414             :                  */
    1415           0 :                 if (m == NULL || m->m_len != 1 ||
    1416           0 :                    (loop = *(mtod(m, u_char *))) > 1) {
    1417             :                         error = EINVAL;
    1418           0 :                         break;
    1419             :                 }
    1420           0 :                 imo->imo_loop = loop;
    1421           0 :                 break;
    1422             : 
    1423             :         case IP_ADD_MEMBERSHIP:
    1424             :                 /*
    1425             :                  * Add a multicast group membership.
    1426             :                  * Group must be a valid IP multicast address.
    1427             :                  */
    1428           0 :                 if (m == NULL || m->m_len != sizeof(struct ip_mreq)) {
    1429             :                         error = EINVAL;
    1430           0 :                         break;
    1431             :                 }
    1432           0 :                 mreq = mtod(m, struct ip_mreq *);
    1433           0 :                 if (!IN_MULTICAST(mreq->imr_multiaddr.s_addr)) {
    1434             :                         error = EINVAL;
    1435           0 :                         break;
    1436             :                 }
    1437             :                 /*
    1438             :                  * If no interface address was provided, use the interface of
    1439             :                  * the route to the given multicast address.
    1440             :                  */
    1441           0 :                 if (mreq->imr_interface.s_addr == INADDR_ANY) {
    1442             :                         memset(&sin, 0, sizeof(sin));
    1443             :                         sin.sin_len = sizeof(sin);
    1444             :                         sin.sin_family = AF_INET;
    1445           0 :                         sin.sin_addr = mreq->imr_multiaddr;
    1446           0 :                         rt = rtalloc(sintosa(&sin), RT_RESOLVE, rtableid);
    1447           0 :                         if (!rtisvalid(rt)) {
    1448           0 :                                 rtfree(rt);
    1449             :                                 error = EADDRNOTAVAIL;
    1450           0 :                                 break;
    1451             :                         }
    1452             :                 } else {
    1453             :                         memset(&sin, 0, sizeof(sin));
    1454             :                         sin.sin_len = sizeof(sin);
    1455             :                         sin.sin_family = AF_INET;
    1456           0 :                         sin.sin_addr = mreq->imr_interface;
    1457           0 :                         rt = rtalloc(sintosa(&sin), 0, rtableid);
    1458           0 :                         if (!rtisvalid(rt) || !ISSET(rt->rt_flags, RTF_LOCAL)) {
    1459           0 :                                 rtfree(rt);
    1460             :                                 error = EADDRNOTAVAIL;
    1461           0 :                                 break;
    1462             :                         }
    1463             :                 }
    1464           0 :                 ifp = if_get(rt->rt_ifidx);
    1465           0 :                 rtfree(rt);
    1466             : 
    1467             :                 /*
    1468             :                  * See if we found an interface, and confirm that it
    1469             :                  * supports multicast.
    1470             :                  */
    1471           0 :                 if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0) {
    1472             :                         error = EADDRNOTAVAIL;
    1473           0 :                         if_put(ifp);
    1474           0 :                         break;
    1475             :                 }
    1476             :                 /*
    1477             :                  * See if the membership already exists or if all the
    1478             :                  * membership slots are full.
    1479             :                  */
    1480           0 :                 for (i = 0; i < imo->imo_num_memberships; ++i) {
    1481           0 :                         if (imo->imo_membership[i]->inm_ifidx
    1482           0 :                                                 == ifp->if_index &&
    1483           0 :                             imo->imo_membership[i]->inm_addr.s_addr
    1484           0 :                                                 == mreq->imr_multiaddr.s_addr)
    1485             :                                 break;
    1486             :                 }
    1487           0 :                 if (i < imo->imo_num_memberships) {
    1488             :                         error = EADDRINUSE;
    1489           0 :                         if_put(ifp);
    1490           0 :                         break;
    1491             :                 }
    1492           0 :                 if (imo->imo_num_memberships == imo->imo_max_memberships) {
    1493             :                         struct in_multi **nmships, **omships;
    1494             :                         size_t newmax;
    1495             :                         /*
    1496             :                          * Resize the vector to next power-of-two minus 1. If the
    1497             :                          * size would exceed the maximum then we know we've really
    1498             :                          * run out of entries. Otherwise, we reallocate the vector.
    1499             :                          */
    1500             :                         nmships = NULL;
    1501           0 :                         omships = imo->imo_membership;
    1502           0 :                         newmax = ((imo->imo_max_memberships + 1) * 2) - 1;
    1503           0 :                         if (newmax <= IP_MAX_MEMBERSHIPS) {
    1504           0 :                                 nmships = (struct in_multi **)mallocarray(
    1505             :                                     newmax, sizeof(*nmships), M_IPMOPTS,
    1506             :                                     M_NOWAIT|M_ZERO);
    1507           0 :                                 if (nmships != NULL) {
    1508           0 :                                         memcpy(nmships, omships,
    1509             :                                             sizeof(*omships) *
    1510             :                                             imo->imo_max_memberships);
    1511           0 :                                         free(omships, M_IPMOPTS,
    1512           0 :                                             sizeof(*omships) *
    1513           0 :                                             imo->imo_max_memberships);
    1514           0 :                                         imo->imo_membership = nmships;
    1515           0 :                                         imo->imo_max_memberships = newmax;
    1516           0 :                                 }
    1517             :                         }
    1518           0 :                         if (nmships == NULL) {
    1519             :                                 error = ENOBUFS;
    1520           0 :                                 if_put(ifp);
    1521           0 :                                 break;
    1522             :                         }
    1523           0 :                 }
    1524             :                 /*
    1525             :                  * Everything looks good; add a new record to the multicast
    1526             :                  * address list for the given interface.
    1527             :                  */
    1528           0 :                 if ((imo->imo_membership[i] =
    1529           0 :                     in_addmulti(&mreq->imr_multiaddr, ifp)) == NULL) {
    1530             :                         error = ENOBUFS;
    1531           0 :                         if_put(ifp);
    1532           0 :                         break;
    1533             :                 }
    1534           0 :                 ++imo->imo_num_memberships;
    1535           0 :                 if_put(ifp);
    1536           0 :                 break;
    1537             : 
    1538             :         case IP_DROP_MEMBERSHIP:
    1539             :                 /*
    1540             :                  * Drop a multicast group membership.
    1541             :                  * Group must be a valid IP multicast address.
    1542             :                  */
    1543           0 :                 if (m == NULL || m->m_len != sizeof(struct ip_mreq)) {
    1544             :                         error = EINVAL;
    1545           0 :                         break;
    1546             :                 }
    1547           0 :                 mreq = mtod(m, struct ip_mreq *);
    1548           0 :                 if (!IN_MULTICAST(mreq->imr_multiaddr.s_addr)) {
    1549             :                         error = EINVAL;
    1550           0 :                         break;
    1551             :                 }
    1552             :                 /*
    1553             :                  * If an interface address was specified, get a pointer
    1554             :                  * to its ifnet structure.
    1555             :                  */
    1556           0 :                 if (mreq->imr_interface.s_addr == INADDR_ANY)
    1557           0 :                         ifp = NULL;
    1558             :                 else {
    1559           0 :                         memset(&sin, 0, sizeof(sin));
    1560           0 :                         sin.sin_len = sizeof(sin);
    1561           0 :                         sin.sin_family = AF_INET;
    1562           0 :                         sin.sin_addr = mreq->imr_interface;
    1563           0 :                         ia = ifatoia(ifa_ifwithaddr(sintosa(&sin), rtableid));
    1564           0 :                         if (ia == NULL) {
    1565             :                                 error = EADDRNOTAVAIL;
    1566           0 :                                 break;
    1567             :                         }
    1568           0 :                         ifp = ia->ia_ifp;
    1569             :                 }
    1570             :                 /*
    1571             :                  * Find the membership in the membership array.
    1572             :                  */
    1573           0 :                 for (i = 0; i < imo->imo_num_memberships; ++i) {
    1574           0 :                         if ((ifp == NULL ||
    1575           0 :                             imo->imo_membership[i]->inm_ifidx ==
    1576           0 :                                 ifp->if_index) &&
    1577           0 :                              imo->imo_membership[i]->inm_addr.s_addr ==
    1578           0 :                              mreq->imr_multiaddr.s_addr)
    1579             :                                 break;
    1580             :                 }
    1581           0 :                 if (i == imo->imo_num_memberships) {
    1582             :                         error = EADDRNOTAVAIL;
    1583           0 :                         break;
    1584             :                 }
    1585             :                 /*
    1586             :                  * Give up the multicast address record to which the
    1587             :                  * membership points.
    1588             :                  */
    1589           0 :                 in_delmulti(imo->imo_membership[i]);
    1590             :                 /*
    1591             :                  * Remove the gap in the membership array.
    1592             :                  */
    1593           0 :                 for (++i; i < imo->imo_num_memberships; ++i)
    1594           0 :                         imo->imo_membership[i-1] = imo->imo_membership[i];
    1595           0 :                 --imo->imo_num_memberships;
    1596           0 :                 break;
    1597             : 
    1598             :         default:
    1599             :                 error = EOPNOTSUPP;
    1600           0 :                 break;
    1601             :         }
    1602             : 
    1603             :         /*
    1604             :          * If all options have default values, no need to keep the data.
    1605             :          */
    1606           0 :         if (imo->imo_ifidx == 0 &&
    1607           0 :             imo->imo_ttl == IP_DEFAULT_MULTICAST_TTL &&
    1608           0 :             imo->imo_loop == IP_DEFAULT_MULTICAST_LOOP &&
    1609           0 :             imo->imo_num_memberships == 0) {
    1610           0 :                 free(imo->imo_membership , M_IPMOPTS, 0);
    1611           0 :                 free(*imop, M_IPMOPTS, sizeof(**imop));
    1612           0 :                 *imop = NULL;
    1613           0 :         }
    1614             : 
    1615           0 :         return (error);
    1616           0 : }
    1617             : 
    1618             : /*
    1619             :  * Return the IP multicast options in response to user getsockopt().
    1620             :  */
    1621             : int
    1622           0 : ip_getmoptions(int optname, struct ip_moptions *imo, struct mbuf *m)
    1623             : {
    1624             :         u_char *ttl;
    1625             :         u_char *loop;
    1626             :         struct in_addr *addr;
    1627             :         struct in_ifaddr *ia;
    1628             :         struct ifnet *ifp;
    1629             : 
    1630           0 :         switch (optname) {
    1631             : 
    1632             :         case IP_MULTICAST_IF:
    1633           0 :                 addr = mtod(m, struct in_addr *);
    1634           0 :                 m->m_len = sizeof(struct in_addr);
    1635           0 :                 if (imo == NULL || (ifp = if_get(imo->imo_ifidx)) == NULL)
    1636           0 :                         addr->s_addr = INADDR_ANY;
    1637             :                 else {
    1638           0 :                         IFP_TO_IA(ifp, ia);
    1639           0 :                         if_put(ifp);
    1640           0 :                         addr->s_addr = (ia == NULL) ? INADDR_ANY
    1641           0 :                                         : ia->ia_addr.sin_addr.s_addr;
    1642             :                 }
    1643           0 :                 return (0);
    1644             : 
    1645             :         case IP_MULTICAST_TTL:
    1646           0 :                 ttl = mtod(m, u_char *);
    1647           0 :                 m->m_len = 1;
    1648           0 :                 *ttl = (imo == NULL) ? IP_DEFAULT_MULTICAST_TTL
    1649           0 :                                      : imo->imo_ttl;
    1650           0 :                 return (0);
    1651             : 
    1652             :         case IP_MULTICAST_LOOP:
    1653           0 :                 loop = mtod(m, u_char *);
    1654           0 :                 m->m_len = 1;
    1655           0 :                 *loop = (imo == NULL) ? IP_DEFAULT_MULTICAST_LOOP
    1656           0 :                                       : imo->imo_loop;
    1657           0 :                 return (0);
    1658             : 
    1659             :         default:
    1660           0 :                 return (EOPNOTSUPP);
    1661             :         }
    1662           0 : }
    1663             : 
    1664             : /*
    1665             :  * Discard the IP multicast options.
    1666             :  */
    1667             : void
    1668           0 : ip_freemoptions(struct ip_moptions *imo)
    1669             : {
    1670             :         int i;
    1671             : 
    1672           0 :         if (imo != NULL) {
    1673           0 :                 for (i = 0; i < imo->imo_num_memberships; ++i)
    1674           0 :                         in_delmulti(imo->imo_membership[i]);
    1675           0 :                 free(imo->imo_membership, M_IPMOPTS, 0);
    1676           0 :                 free(imo, M_IPMOPTS, sizeof(*imo));
    1677           0 :         }
    1678           0 : }
    1679             : 
    1680             : /*
    1681             :  * Routine called from ip_output() to loop back a copy of an IP multicast
    1682             :  * packet to the input queue of a specified interface.
    1683             :  */
    1684             : void
    1685           0 : ip_mloopback(struct ifnet *ifp, struct mbuf *m, struct sockaddr_in *dst)
    1686             : {
    1687             :         struct ip *ip;
    1688             :         struct mbuf *copym;
    1689             : 
    1690           0 :         copym = m_dup_pkt(m, max_linkhdr, M_DONTWAIT);
    1691           0 :         if (copym != NULL) {
    1692             :                 /*
    1693             :                  * We don't bother to fragment if the IP length is greater
    1694             :                  * than the interface's MTU.  Can this possibly matter?
    1695             :                  */
    1696           0 :                 ip = mtod(copym, struct ip *);
    1697           0 :                 ip->ip_sum = 0;
    1698           0 :                 ip->ip_sum = in_cksum(copym, ip->ip_hl << 2);
    1699           0 :                 if_input_local(ifp, copym, dst->sin_family);
    1700           0 :         }
    1701           0 : }
    1702             : 
    1703             : /*
    1704             :  *      Compute significant parts of the IPv4 checksum pseudo-header
    1705             :  *      for use in a delayed TCP/UDP checksum calculation.
    1706             :  */
    1707             : static __inline u_int16_t __attribute__((__unused__))
    1708           0 : in_cksum_phdr(u_int32_t src, u_int32_t dst, u_int32_t lenproto)
    1709             : {
    1710             :         u_int32_t sum;
    1711             : 
    1712           0 :         sum = lenproto +
    1713           0 :               (u_int16_t)(src >> 16) +
    1714           0 :               (u_int16_t)(src /*& 0xffff*/) +
    1715           0 :               (u_int16_t)(dst >> 16) +
    1716           0 :               (u_int16_t)(dst /*& 0xffff*/);
    1717             : 
    1718           0 :         sum = (u_int16_t)(sum >> 16) + (u_int16_t)(sum /*& 0xffff*/);
    1719             : 
    1720           0 :         if (sum > 0xffff)
    1721           0 :                 sum -= 0xffff;
    1722             : 
    1723           0 :         return (sum);
    1724             : }
    1725             : 
    1726             : /*
    1727             :  * Process a delayed payload checksum calculation.
    1728             :  */
    1729             : void
    1730           0 : in_delayed_cksum(struct mbuf *m)
    1731             : {
    1732             :         struct ip *ip;
    1733           0 :         u_int16_t csum, offset;
    1734             : 
    1735           0 :         ip = mtod(m, struct ip *);
    1736           0 :         offset = ip->ip_hl << 2;
    1737           0 :         csum = in4_cksum(m, 0, offset, m->m_pkthdr.len - offset);
    1738           0 :         if (csum == 0 && ip->ip_p == IPPROTO_UDP)
    1739           0 :                 csum = 0xffff;
    1740             : 
    1741           0 :         switch (ip->ip_p) {
    1742             :         case IPPROTO_TCP:
    1743           0 :                 offset += offsetof(struct tcphdr, th_sum);
    1744           0 :                 break;
    1745             : 
    1746             :         case IPPROTO_UDP:
    1747           0 :                 offset += offsetof(struct udphdr, uh_sum);
    1748           0 :                 break;
    1749             : 
    1750             :         case IPPROTO_ICMP:
    1751           0 :                 offset += offsetof(struct icmp, icmp_cksum);
    1752           0 :                 break;
    1753             : 
    1754             :         default:
    1755           0 :                 return;
    1756             :         }
    1757             : 
    1758           0 :         if ((offset + sizeof(u_int16_t)) > m->m_len)
    1759           0 :                 m_copyback(m, offset, sizeof(csum), &csum, M_NOWAIT);
    1760             :         else
    1761           0 :                 *(u_int16_t *)(mtod(m, caddr_t) + offset) = csum;
    1762           0 : }
    1763             : 
    1764             : void
    1765           0 : in_proto_cksum_out(struct mbuf *m, struct ifnet *ifp)
    1766             : {
    1767           0 :         struct ip *ip = mtod(m, struct ip *);
    1768             : 
    1769             :         /* some hw and in_delayed_cksum need the pseudo header cksum */
    1770           0 :         if (m->m_pkthdr.csum_flags &
    1771             :             (M_TCP_CSUM_OUT|M_UDP_CSUM_OUT|M_ICMP_CSUM_OUT)) {
    1772           0 :                 u_int16_t csum = 0, offset;
    1773             : 
    1774           0 :                 offset = ip->ip_hl << 2;
    1775           0 :                 if (m->m_pkthdr.csum_flags & (M_TCP_CSUM_OUT|M_UDP_CSUM_OUT))
    1776           0 :                         csum = in_cksum_phdr(ip->ip_src.s_addr,
    1777           0 :                             ip->ip_dst.s_addr, htonl(ntohs(ip->ip_len) -
    1778             :                             offset + ip->ip_p));
    1779           0 :                 if (ip->ip_p == IPPROTO_TCP)
    1780           0 :                         offset += offsetof(struct tcphdr, th_sum);
    1781           0 :                 else if (ip->ip_p == IPPROTO_UDP)
    1782           0 :                         offset += offsetof(struct udphdr, uh_sum);
    1783           0 :                 else if (ip->ip_p == IPPROTO_ICMP)
    1784           0 :                         offset += offsetof(struct icmp, icmp_cksum);
    1785           0 :                 if ((offset + sizeof(u_int16_t)) > m->m_len)
    1786           0 :                         m_copyback(m, offset, sizeof(csum), &csum, M_NOWAIT);
    1787             :                 else
    1788           0 :                         *(u_int16_t *)(mtod(m, caddr_t) + offset) = csum;
    1789           0 :         }
    1790             : 
    1791           0 :         if (m->m_pkthdr.csum_flags & M_TCP_CSUM_OUT) {
    1792           0 :                 if (!ifp || !(ifp->if_capabilities & IFCAP_CSUM_TCPv4) ||
    1793           0 :                     ip->ip_hl != 5 || ifp->if_bridgeport != NULL) {
    1794           0 :                         tcpstat_inc(tcps_outswcsum);
    1795           0 :                         in_delayed_cksum(m);
    1796           0 :                         m->m_pkthdr.csum_flags &= ~M_TCP_CSUM_OUT; /* Clear */
    1797           0 :                 }
    1798           0 :         } else if (m->m_pkthdr.csum_flags & M_UDP_CSUM_OUT) {
    1799           0 :                 if (!ifp || !(ifp->if_capabilities & IFCAP_CSUM_UDPv4) ||
    1800           0 :                     ip->ip_hl != 5 || ifp->if_bridgeport != NULL) {
    1801           0 :                         udpstat_inc(udps_outswcsum);
    1802           0 :                         in_delayed_cksum(m);
    1803           0 :                         m->m_pkthdr.csum_flags &= ~M_UDP_CSUM_OUT; /* Clear */
    1804           0 :                 }
    1805           0 :         } else if (m->m_pkthdr.csum_flags & M_ICMP_CSUM_OUT) {
    1806           0 :                 in_delayed_cksum(m);
    1807           0 :                 m->m_pkthdr.csum_flags &= ~M_ICMP_CSUM_OUT; /* Clear */
    1808           0 :         }
    1809           0 : }

Generated by: LCOV version 1.13