darwin-xnu/bsd/netinet/udp_usrreq.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
   3 *
   4 * @APPLE_LICENSE_HEADER_START@
   5 * 
   6 * The contents of this file constitute Original Code as defined in and
   7 * are subject to the Apple Public Source License Version 1.1 (the
   8 * "License").  You may not use this file except in compliance with the
   9 * License.  Please obtain a copy of the License at
  10 * http://www.apple.com/publicsource and read it before using this file.
  11 * 
  12 * This Original Code and all software distributed under the License are
  13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
  16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
  17 * License for the specific language governing rights and limitations
  18 * under the License.
  19 * 
  20 * @APPLE_LICENSE_HEADER_END@
  21 */
  22/*
  23 * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
  24 *      The Regents of the University of California.  All rights reserved.
  25 *
  26 * Redistribution and use in source and binary forms, with or without
  27 * modification, are permitted provided that the following conditions
  28 * are met:
  29 * 1. Redistributions of source code must retain the above copyright
  30 *    notice, this list of conditions and the following disclaimer.
  31 * 2. Redistributions in binary form must reproduce the above copyright
  32 *    notice, this list of conditions and the following disclaimer in the
  33 *    documentation and/or other materials provided with the distribution.
  34 * 3. All advertising materials mentioning features or use of this software
  35 *    must display the following acknowledgement:
  36 *      This product includes software developed by the University of
  37 *      California, Berkeley and its contributors.
  38 * 4. Neither the name of the University nor the names of its contributors
  39 *    may be used to endorse or promote products derived from this software
  40 *    without specific prior written permission.
  41 *
  42 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  43 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  44 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  45 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  46 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  47 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  48 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  49 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  50 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  51 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  52 * SUCH DAMAGE.
  53 *
  54 *      @(#)udp_usrreq.c        8.6 (Berkeley) 5/23/95
  55 * $FreeBSD: src/sys/netinet/udp_usrreq.c,v 1.64.2.13 2001/08/08 18:59:54 ghelmer Exp $
  56 */
  57
  58#include <sys/param.h>
  59#include <sys/systm.h>
  60#include <sys/kernel.h>
  61#include <sys/malloc.h>
  62#include <sys/mbuf.h>
  63#include <sys/domain.h>
  64#include <sys/protosw.h>
  65#include <sys/socket.h>
  66#include <sys/socketvar.h>
  67#include <sys/sysctl.h>
  68#include <sys/syslog.h>
  69
  70#include <net/if.h>
  71#include <net/if_types.h>
  72#include <net/route.h>
  73
  74#include <netinet/in.h>
  75#include <netinet/in_systm.h>
  76#include <netinet/ip.h>
  77#if INET6
  78#include <netinet/ip6.h>
  79#endif
  80#include <netinet/in_pcb.h>
  81#include <netinet/in_var.h>
  82#include <netinet/ip_var.h>
  83#if INET6
  84#include <netinet6/ip6_var.h>
  85#endif
  86#include <netinet/ip_icmp.h>
  87#include <netinet/icmp_var.h>
  88#include <netinet/udp.h>
  89#include <netinet/udp_var.h>
  90#include <sys/kdebug.h>
  91
  92#if IPSEC
  93#include <netinet6/ipsec.h>
  94extern int ipsec_bypass;
  95extern lck_mtx_t *sadb_mutex;
  96#endif /*IPSEC*/
  97
  98
  99#define DBG_LAYER_IN_BEG        NETDBG_CODE(DBG_NETUDP, 0)
 100#define DBG_LAYER_IN_END        NETDBG_CODE(DBG_NETUDP, 2)
 101#define DBG_LAYER_OUT_BEG       NETDBG_CODE(DBG_NETUDP, 1)
 102#define DBG_LAYER_OUT_END       NETDBG_CODE(DBG_NETUDP, 3)
 103#define DBG_FNC_UDP_INPUT       NETDBG_CODE(DBG_NETUDP, (5 << 8))
 104#define DBG_FNC_UDP_OUTPUT      NETDBG_CODE(DBG_NETUDP, (6 << 8) | 1)
 105
 106/*
 107 * UDP protocol implementation.
 108 * Per RFC 768, August, 1980.
 109 */
 110#ifndef COMPAT_42
 111static int      udpcksum = 1;
 112#else
 113static int      udpcksum = 0;           /* XXX */
 114#endif
 115SYSCTL_INT(_net_inet_udp, UDPCTL_CHECKSUM, checksum, CTLFLAG_RW,
 116                &udpcksum, 0, "");
 117
 118int     log_in_vain = 0;
 119SYSCTL_INT(_net_inet_udp, OID_AUTO, log_in_vain, CTLFLAG_RW, 
 120    &log_in_vain, 0, "Log all incoming UDP packets");
 121
 122static int      blackhole = 0;
 123SYSCTL_INT(_net_inet_udp, OID_AUTO, blackhole, CTLFLAG_RW,
 124        &blackhole, 0, "Do not send port unreachables for refused connects");
 125
 126struct  inpcbhead udb;          /* from udp_var.h */
 127#define udb6    udb  /* for KAME src sync over BSD*'s */
 128struct  inpcbinfo udbinfo;
 129
 130#ifndef UDBHASHSIZE
 131#define UDBHASHSIZE 16
 132#endif
 133
 134extern  int apple_hwcksum_rx;
 135extern  int     esp_udp_encap_port;
 136extern  u_long  route_generation;
 137
 138extern  void    ipfwsyslog( int level, char *format,...);
 139 
 140extern int fw_verbose;
 141
 142#define log_in_vain_log( a ) {            \
 143        if ( (log_in_vain == 3 ) && (fw_verbose == 2)) {        /* Apple logging, log to ipfw.log */ \
 144                ipfwsyslog a ;  \
 145        }                       \
 146        else log a ;            \
 147}
 148
 149struct  udpstat udpstat;        /* from udp_var.h */
 150SYSCTL_STRUCT(_net_inet_udp, UDPCTL_STATS, stats, CTLFLAG_RD,
 151    &udpstat, udpstat, "UDP statistics (struct udpstat, netinet/udp_var.h)");
 152SYSCTL_INT(_net_inet_udp, OID_AUTO, pcbcount, CTLFLAG_RD, 
 153    &udbinfo.ipi_count, 0, "Number of active PCBs");
 154
 155static struct   sockaddr_in udp_in = { sizeof(udp_in), AF_INET };
 156#if INET6
 157struct udp_in6 {
 158        struct sockaddr_in6     uin6_sin;
 159        u_char                  uin6_init_done : 1;
 160} udp_in6 = {
 161        { sizeof(udp_in6.uin6_sin), AF_INET6 },
 162        0
 163};
 164struct udp_ip6 {
 165        struct ip6_hdr          uip6_ip6;
 166        u_char                  uip6_init_done : 1;
 167} udp_ip6;
 168#endif /* INET6 */
 169
 170static void udp_append(struct inpcb *last, struct ip *ip,
 171                            struct mbuf *n, int off);
 172#if INET6
 173static void ip_2_ip6_hdr(struct ip6_hdr *ip6, struct ip *ip);
 174#endif
 175
 176static int udp_detach(struct socket *so);
 177static  int udp_output(struct inpcb *, struct mbuf *, struct sockaddr *,
 178                            struct mbuf *, struct proc *);
 179extern int ChkAddressOK( __uint32_t dstaddr, __uint32_t srcaddr );
 180
 181void
 182udp_init()
 183{
 184        vm_size_t                       str_size;
 185        struct inpcbinfo        *pcbinfo;
 186        
 187
 188        LIST_INIT(&udb);
 189        udbinfo.listhead = &udb;
 190        udbinfo.hashbase = hashinit(UDBHASHSIZE, M_PCB, &udbinfo.hashmask);
 191        udbinfo.porthashbase = hashinit(UDBHASHSIZE, M_PCB,
 192                                        &udbinfo.porthashmask);
 193#ifdef __APPLE__
 194        str_size = (vm_size_t) sizeof(struct inpcb);
 195        udbinfo.ipi_zone = (void *) zinit(str_size, 80000*str_size, 8192, "udpcb");
 196
 197        pcbinfo = &udbinfo;
 198        /*
 199         * allocate lock group attribute and group for udp pcb mutexes
 200         */
 201        pcbinfo->mtx_grp_attr = lck_grp_attr_alloc_init();
 202        lck_grp_attr_setdefault(pcbinfo->mtx_grp_attr);
 203
 204        pcbinfo->mtx_grp = lck_grp_alloc_init("udppcb", pcbinfo->mtx_grp_attr);
 205                
 206        pcbinfo->mtx_attr = lck_attr_alloc_init();
 207        lck_attr_setdefault(pcbinfo->mtx_attr);
 208
 209        if ((pcbinfo->mtx = lck_rw_alloc_init(pcbinfo->mtx_grp, pcbinfo->mtx_attr)) == NULL)
 210                return; /* pretty much dead if this fails... */
 211
 212        in_pcb_nat_init(&udbinfo, AF_INET, IPPROTO_UDP, SOCK_DGRAM);
 213#else
 214        udbinfo.ipi_zone = zinit("udpcb", sizeof(struct inpcb), maxsockets,
 215                                 ZONE_INTERRUPT, 0);
 216#endif
 217
 218#if 0
 219        /* for pcb sharing testing only */
 220        stat = in_pcb_new_share_client(&udbinfo, &fake_owner);
 221        kprintf("udp_init in_pcb_new_share_client - stat = %d\n", stat);
 222
 223        laddr.s_addr = 0x11646464;
 224        faddr.s_addr = 0x11646465;
 225        
 226        lport = 1500;
 227        in_pcb_grab_port(&udbinfo, 0, laddr, &lport, faddr, 1600, 0, fake_owner); 
 228        kprintf("udp_init in_pcb_grab_port - stat = %d\n", stat);
 229
 230        stat = in_pcb_rem_share_client(&udbinfo, fake_owner);
 231        kprintf("udp_init in_pcb_rem_share_client - stat = %d\n", stat);
 232
 233        stat = in_pcb_new_share_client(&udbinfo, &fake_owner);
 234        kprintf("udp_init in_pcb_new_share_client(2) - stat = %d\n", stat);
 235
 236        laddr.s_addr = 0x11646464;
 237        faddr.s_addr = 0x11646465;
 238        
 239        lport = 1500;
 240        stat = in_pcb_grab_port(&udbinfo, 0, laddr, &lport, faddr, 1600, 0, fake_owner); 
 241        kprintf("udp_init in_pcb_grab_port(2) - stat = %d\n", stat);
 242#endif
 243}
 244
 245void
 246udp_input(m, iphlen)
 247        register struct mbuf *m;
 248        int iphlen;
 249{
 250        register struct ip *ip;
 251        register struct udphdr *uh;
 252        register struct inpcb *inp;
 253        struct mbuf *opts = 0;
 254        int len;
 255        struct ip save_ip;
 256        struct sockaddr *append_sa;
 257        struct inpcbinfo *pcbinfo = &udbinfo;
 258
 259        udpstat.udps_ipackets++;
 260
 261        KERNEL_DEBUG(DBG_FNC_UDP_INPUT | DBG_FUNC_START, 0,0,0,0,0);
 262        if (m->m_pkthdr.csum_flags & CSUM_TCP_SUM16)
 263                m->m_pkthdr.csum_flags = 0; /* invalidate hwcksum for UDP */
 264
 265        /*
 266         * Strip IP options, if any; should skip this,
 267         * make available to user, and use on returned packets,
 268         * but we don't yet have a way to check the checksum
 269         * with options still present.
 270         */
 271        if (iphlen > sizeof (struct ip)) {
 272                ip_stripoptions(m, (struct mbuf *)0);
 273                iphlen = sizeof(struct ip);
 274        }
 275
 276        /*
 277         * Get IP and UDP header together in first mbuf.
 278         */
 279        ip = mtod(m, struct ip *);
 280        if (m->m_len < iphlen + sizeof(struct udphdr)) {
 281                if ((m = m_pullup(m, iphlen + sizeof(struct udphdr))) == 0) {
 282                        udpstat.udps_hdrops++;
 283                        KERNEL_DEBUG(DBG_FNC_UDP_INPUT | DBG_FUNC_END, 0,0,0,0,0);
 284                        return;
 285                }
 286                ip = mtod(m, struct ip *);
 287        }
 288        uh = (struct udphdr *)((caddr_t)ip + iphlen);
 289
 290        /* destination port of 0 is illegal, based on RFC768. */
 291        if (uh->uh_dport == 0)
 292                goto bad;
 293
 294        KERNEL_DEBUG(DBG_LAYER_IN_BEG, uh->uh_dport, uh->uh_sport,
 295                     ip->ip_src.s_addr, ip->ip_dst.s_addr, uh->uh_ulen);
 296
 297        /*
 298         * Make mbuf data length reflect UDP length.
 299         * If not enough data to reflect UDP length, drop.
 300         */
 301        len = ntohs((u_short)uh->uh_ulen);
 302        if (ip->ip_len != len) {
 303                if (len > ip->ip_len || len < sizeof(struct udphdr)) {
 304                        udpstat.udps_badlen++;
 305                        goto bad;
 306                }
 307                m_adj(m, len - ip->ip_len);
 308                /* ip->ip_len = len; */
 309        }
 310        /*
 311         * Save a copy of the IP header in case we want restore it
 312         * for sending an ICMP error message in response.
 313         */
 314        save_ip = *ip;
 315
 316        /*
 317         * Checksum extended UDP header and data.
 318         */
 319        if (uh->uh_sum) {
 320                if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID) {
 321                        if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR)
 322                                uh->uh_sum = m->m_pkthdr.csum_data;
 323                        else
 324                                goto doudpcksum;
 325                        uh->uh_sum ^= 0xffff;
 326                } else {
 327                        char b[9];
 328doudpcksum:
 329                        *(uint32_t*)&b[0] = *(uint32_t*)&((struct ipovly *)ip)->ih_x1[0];
 330                        *(uint32_t*)&b[4] = *(uint32_t*)&((struct ipovly *)ip)->ih_x1[4];
 331                        *(uint8_t*)&b[8] = *(uint8_t*)&((struct ipovly *)ip)->ih_x1[8];
 332                        
 333                        bzero(((struct ipovly *)ip)->ih_x1, 9);
 334                        ((struct ipovly *)ip)->ih_len = uh->uh_ulen;
 335                        uh->uh_sum = in_cksum(m, len + sizeof (struct ip));
 336                        
 337                        *(uint32_t*)&((struct ipovly *)ip)->ih_x1[0] = *(uint32_t*)&b[0];
 338                        *(uint32_t*)&((struct ipovly *)ip)->ih_x1[4] = *(uint32_t*)&b[4];
 339                        *(uint8_t*)&((struct ipovly *)ip)->ih_x1[8] = *(uint8_t*)&b[8];
 340                }
 341                if (uh->uh_sum) {
 342                        udpstat.udps_badsum++;
 343                        m_freem(m);
 344                        KERNEL_DEBUG(DBG_FNC_UDP_INPUT | DBG_FUNC_END, 0,0,0,0,0);
 345                        return;
 346                }
 347        }
 348#ifndef __APPLE__
 349         else
 350                udpstat.udps_nosum++;
 351#endif
 352
 353        if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) ||
 354            in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif)) {
 355                struct inpcb *last;
 356                lck_rw_lock_shared(pcbinfo->mtx);
 357                /*
 358                 * Deliver a multicast or broadcast datagram to *all* sockets
 359                 * for which the local and remote addresses and ports match
 360                 * those of the incoming datagram.  This allows more than
 361                 * one process to receive multi/broadcasts on the same port.
 362                 * (This really ought to be done for unicast datagrams as
 363                 * well, but that would cause problems with existing
 364                 * applications that open both address-specific sockets and
 365                 * a wildcard socket listening to the same port -- they would
 366                 * end up receiving duplicates of every unicast datagram.
 367                 * Those applications open the multiple sockets to overcome an
 368                 * inadequacy of the UDP socket interface, but for backwards
 369                 * compatibility we avoid the problem here rather than
 370                 * fixing the interface.  Maybe 4.5BSD will remedy this?)
 371                 */
 372
 373
 374                /*
 375                 * Construct sockaddr format source address.
 376                 */
 377                udp_in.sin_port = uh->uh_sport;
 378                udp_in.sin_addr = ip->ip_src;
 379                /*
 380                 * Locate pcb(s) for datagram.
 381                 * (Algorithm copied from raw_intr().)
 382                 */
 383                last = NULL;
 384#if INET6
 385                udp_in6.uin6_init_done = udp_ip6.uip6_init_done = 0;
 386#endif
 387                LIST_FOREACH(inp, &udb, inp_list) {
 388#ifdef __APPLE__
 389                        /* Ignore nat/SharedIP dummy pcbs */
 390                        if (inp->inp_socket == &udbinfo.nat_dummy_socket)
 391                                continue;
 392#endif
 393                        if (inp->inp_socket == NULL) 
 394                                continue;
 395                        if (inp != sotoinpcb(inp->inp_socket))
 396                                panic("udp_input: bad so back ptr inp=%x\n", inp);
 397#if INET6
 398                        if ((inp->inp_vflag & INP_IPV4) == 0)
 399                                continue;
 400#endif
 401                        if (in_pcb_checkstate(inp, WNT_ACQUIRE, 0) == WNT_STOPUSING) {
 402                                continue;
 403                        }
 404                        
 405                        udp_lock(inp->inp_socket, 1, 0);        
 406
 407                        if (in_pcb_checkstate(inp, WNT_RELEASE, 1) == WNT_STOPUSING) {
 408                                udp_unlock(inp->inp_socket, 1, 0);
 409                                continue;
 410                        }
 411
 412                        if (inp->inp_lport != uh->uh_dport) {
 413                                udp_unlock(inp->inp_socket, 1, 0);
 414                                continue;
 415                        }
 416                        if (inp->inp_laddr.s_addr != INADDR_ANY) {
 417                                if (inp->inp_laddr.s_addr !=
 418                                    ip->ip_dst.s_addr) {
 419                                        udp_unlock(inp->inp_socket, 1, 0);
 420                                        continue;
 421                                }
 422                        }
 423                        if (inp->inp_faddr.s_addr != INADDR_ANY) {
 424                                if (inp->inp_faddr.s_addr !=
 425                                    ip->ip_src.s_addr ||
 426                                    inp->inp_fport != uh->uh_sport) {
 427                                        udp_unlock(inp->inp_socket, 1, 0);
 428                                        continue;
 429                                }
 430                        }
 431
 432                        if (last != NULL) {
 433                                struct mbuf *n;
 434#if IPSEC
 435                                int skipit = 0;
 436                                /* check AH/ESP integrity. */
 437                                if (ipsec_bypass == 0) {
 438                                        lck_mtx_lock(sadb_mutex);
 439                                        if (ipsec4_in_reject_so(m, last->inp_socket)) {
 440                                                ipsecstat.in_polvio++;
 441                                                /* do not inject data to pcb */
 442                                                skipit = 1;
 443                                        }
 444                                        lck_mtx_unlock(sadb_mutex);
 445                                }
 446                                if (skipit == 0)
 447#endif /*IPSEC*/
 448                                if ((n = m_copy(m, 0, M_COPYALL)) != NULL) {
 449                                        udp_append(last, ip, n,
 450                                                   iphlen +
 451                                                   sizeof(struct udphdr));
 452                                }
 453                                udp_unlock(last->inp_socket, 1, 0);
 454                        }
 455                        last = inp;
 456                        /*
 457                         * Don't look for additional matches if this one does
 458                         * not have either the SO_REUSEPORT or SO_REUSEADDR
 459                         * socket options set.  This heuristic avoids searching
 460                         * through all pcbs in the common case of a non-shared
 461                         * port.  It * assumes that an application will never
 462                         * clear these options after setting them.
 463                         */
 464                        if ((last->inp_socket->so_options&(SO_REUSEPORT|SO_REUSEADDR)) == 0)
 465                                break;
 466                }
 467                lck_rw_done(pcbinfo->mtx);
 468
 469                if (last == NULL) {
 470                        /*
 471                         * No matching pcb found; discard datagram.
 472                         * (No need to send an ICMP Port Unreachable
 473                         * for a broadcast or multicast datgram.)
 474                         */
 475                        udpstat.udps_noportbcast++;
 476                        goto bad;
 477                }
 478#if IPSEC
 479                /* check AH/ESP integrity. */
 480                if (ipsec_bypass == 0 && m) {
 481                        lck_mtx_lock(sadb_mutex);
 482                        if (ipsec4_in_reject_so(m, last->inp_socket)) {
 483                                ipsecstat.in_polvio++;
 484                                lck_mtx_unlock(sadb_mutex);
 485                                udp_unlock(last->inp_socket, 1, 0);
 486                                goto bad;
 487                        }
 488                        lck_mtx_unlock(sadb_mutex);
 489                }
 490#endif /*IPSEC*/
 491                udp_append(last, ip, m, iphlen + sizeof(struct udphdr));
 492                udp_unlock(last->inp_socket, 1, 0);
 493                return;
 494        }
 495
 496#if IPSEC
 497        /*
 498         * UDP to port 4500 with a payload where the first four bytes are
 499         * not zero is a UDP encapsulated IPSec packet. Packets where
 500         * the payload is one byte and that byte is 0xFF are NAT keepalive
 501         * packets. Decapsulate the ESP packet and carry on with IPSec input
 502         * or discard the NAT keep-alive.
 503         */
 504        if (ipsec_bypass == 0 && (esp_udp_encap_port & 0xFFFF) != 0 &&
 505                uh->uh_dport == ntohs((u_short)esp_udp_encap_port)) {
 506                int     payload_len = len - sizeof(struct udphdr) > 4 ? 4 : len - sizeof(struct udphdr);
 507                if (m->m_len < iphlen + sizeof(struct udphdr) + payload_len) {
 508                        if ((m = m_pullup(m, iphlen + sizeof(struct udphdr) + payload_len)) == 0) {
 509                                udpstat.udps_hdrops++;
 510                                KERNEL_DEBUG(DBG_FNC_UDP_INPUT | DBG_FUNC_END, 0,0,0,0,0);
 511                                return;
 512                        }
 513                        ip = mtod(m, struct ip *);
 514                        uh = (struct udphdr *)((caddr_t)ip + iphlen);
 515                }
 516                /* Check for NAT keepalive packet */
 517                if (payload_len == 1 && *(u_int8_t*)((caddr_t)uh + sizeof(struct udphdr)) == 0xFF) {
 518                        m_freem(m);
 519                        KERNEL_DEBUG(DBG_FNC_UDP_INPUT | DBG_FUNC_END, 0,0,0,0,0);
 520                        return;
 521                }
 522                else if (payload_len == 4 && *(u_int32_t*)((caddr_t)uh + sizeof(struct udphdr)) != 0) {
 523                        /* UDP encapsulated IPSec packet to pass through NAT */
 524                        size_t stripsiz;
 525
 526                        stripsiz = sizeof(struct udphdr);
 527
 528                        ip = mtod(m, struct ip *);
 529                        ovbcopy((caddr_t)ip, (caddr_t)(((u_char *)ip) + stripsiz), iphlen);
 530                        m->m_data += stripsiz;
 531                        m->m_len -= stripsiz;
 532                        m->m_pkthdr.len -= stripsiz;
 533                        ip = mtod(m, struct ip *);
 534                        ip->ip_len = ip->ip_len - stripsiz;
 535                        ip->ip_p = IPPROTO_ESP;
 536
 537                        KERNEL_DEBUG(DBG_FNC_UDP_INPUT | DBG_FUNC_END, 0,0,0,0,0);
 538                        esp4_input(m, iphlen);
 539                        return;
 540                }
 541        }
 542#endif
 543
 544        /*
 545         * Locate pcb for datagram.
 546         */
 547        inp = in_pcblookup_hash(&udbinfo, ip->ip_src, uh->uh_sport,
 548            ip->ip_dst, uh->uh_dport, 1, m->m_pkthdr.rcvif);
 549        if (inp == NULL) {
 550                if (log_in_vain) {
 551                        char buf[MAX_IPv4_STR_LEN];
 552                        char buf2[MAX_IPv4_STR_LEN];
 553
 554                        /* check src and dst address */
 555                        if (log_in_vain != 3)
 556                                log(LOG_INFO,
 557                                        "Connection attempt to UDP %s:%d from %s:%d\n",
 558                                        inet_ntop(AF_INET, &ip->ip_dst, buf, sizeof(buf)),
 559                                        ntohs(uh->uh_dport),
 560                                        inet_ntop(AF_INET, &ip->ip_src, buf2, sizeof(buf2)),
 561                                        ntohs(uh->uh_sport));
 562                        else if (!(m->m_flags & (M_BCAST | M_MCAST)) &&
 563                                         ip->ip_dst.s_addr != ip->ip_src.s_addr)
 564                                log_in_vain_log((LOG_INFO,
 565                                        "Stealth Mode connection attempt to UDP %s:%d from %s:%d\n",
 566                                        inet_ntop(AF_INET, &ip->ip_dst, buf, sizeof(buf)),
 567                                        ntohs(uh->uh_dport),
 568                                        inet_ntop(AF_INET, &ip->ip_src, buf2, sizeof(buf2)),
 569                                        ntohs(uh->uh_sport)))
 570                }
 571                udpstat.udps_noport++;
 572                if (m->m_flags & (M_BCAST | M_MCAST)) {
 573                        udpstat.udps_noportbcast++;
 574                        goto bad;
 575                }
 576#if ICMP_BANDLIM
 577                if (badport_bandlim(BANDLIM_ICMP_UNREACH) < 0)
 578                        goto bad;
 579#endif
 580                if (blackhole)
 581                        if (m->m_pkthdr.rcvif && m->m_pkthdr.rcvif->if_type != IFT_LOOP)
 582                                goto bad;
 583                *ip = save_ip;
 584                ip->ip_len += iphlen;
 585                icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT, 0, 0);
 586                KERNEL_DEBUG(DBG_FNC_UDP_INPUT | DBG_FUNC_END, 0,0,0,0,0);
 587                return;
 588        }
 589        udp_lock(inp->inp_socket, 1, 0);
 590
 591        if (in_pcb_checkstate(inp, WNT_RELEASE, 1) == WNT_STOPUSING) {
 592                udp_unlock(inp->inp_socket, 1, 0);
 593                goto bad;
 594        }
 595#if IPSEC
 596        if (ipsec_bypass == 0 && inp != NULL) {
 597                lck_mtx_lock(sadb_mutex);
 598                if (ipsec4_in_reject_so(m, inp->inp_socket)) {
 599                        ipsecstat.in_polvio++;
 600                        lck_mtx_unlock(sadb_mutex);
 601                        udp_unlock(inp->inp_socket, 1, 0);
 602                        goto bad;
 603                }
 604                lck_mtx_unlock(sadb_mutex);
 605        }
 606#endif /*IPSEC*/
 607
 608        /*
 609         * Construct sockaddr format source address.
 610         * Stuff source address and datagram in user buffer.
 611         */
 612        udp_in.sin_port = uh->uh_sport;
 613        udp_in.sin_addr = ip->ip_src;
 614        if (inp->inp_flags & INP_CONTROLOPTS
 615            || inp->inp_socket->so_options & SO_TIMESTAMP) {
 616#if INET6
 617                if (inp->inp_vflag & INP_IPV6) {
 618                        int savedflags;
 619
 620                        ip_2_ip6_hdr(&udp_ip6.uip6_ip6, ip);
 621                        savedflags = inp->inp_flags;
 622                        inp->inp_flags &= ~INP_UNMAPPABLEOPTS;
 623                        ip6_savecontrol(inp, &opts, &udp_ip6.uip6_ip6, m);
 624                        inp->inp_flags = savedflags;
 625                } else
 626#endif
 627                ip_savecontrol(inp, &opts, ip, m);
 628        }
 629        m_adj(m, iphlen + sizeof(struct udphdr));
 630
 631        KERNEL_DEBUG(DBG_LAYER_IN_END, uh->uh_dport, uh->uh_sport,
 632                     save_ip.ip_src.s_addr, save_ip.ip_dst.s_addr, uh->uh_ulen);
 633
 634#if INET6
 635        if (inp->inp_vflag & INP_IPV6) {
 636                in6_sin_2_v4mapsin6(&udp_in, &udp_in6.uin6_sin);
 637                append_sa = (struct sockaddr *)&udp_in6;
 638        } else
 639#endif
 640        append_sa = (struct sockaddr *)&udp_in;
 641        if (sbappendaddr(&inp->inp_socket->so_rcv, append_sa, m, opts, NULL) == 0) {
 642                udpstat.udps_fullsock++;
 643        }
 644        else {
 645                sorwakeup(inp->inp_socket);
 646        }
 647        udp_unlock(inp->inp_socket, 1, 0);
 648        KERNEL_DEBUG(DBG_FNC_UDP_INPUT | DBG_FUNC_END, 0,0,0,0,0);
 649        return;
 650bad:
 651        m_freem(m);
 652        if (opts)
 653                m_freem(opts);
 654        KERNEL_DEBUG(DBG_FNC_UDP_INPUT | DBG_FUNC_END, 0,0,0,0,0);
 655        return;
 656}
 657
 658#if INET6
 659static void
 660ip_2_ip6_hdr(ip6, ip)
 661        struct ip6_hdr *ip6;
 662        struct ip *ip;
 663{
 664        bzero(ip6, sizeof(*ip6));
 665
 666        ip6->ip6_vfc = IPV6_VERSION;
 667        ip6->ip6_plen = ip->ip_len;
 668        ip6->ip6_nxt = ip->ip_p;
 669        ip6->ip6_hlim = ip->ip_ttl;
 670        ip6->ip6_src.s6_addr32[2] = ip6->ip6_dst.s6_addr32[2] =
 671                IPV6_ADDR_INT32_SMP;
 672        ip6->ip6_src.s6_addr32[3] = ip->ip_src.s_addr;
 673        ip6->ip6_dst.s6_addr32[3] = ip->ip_dst.s_addr;
 674}
 675#endif
 676
 677/*
 678 * subroutine of udp_input(), mainly for source code readability.
 679 * caller must properly init udp_ip6 and udp_in6 beforehand.
 680 */
 681static void
 682udp_append(last, ip, n, off)
 683        struct inpcb *last;
 684        struct ip *ip;
 685        struct mbuf *n;
 686        int off;
 687{
 688        struct sockaddr *append_sa;
 689        struct mbuf *opts = 0;
 690
 691        if (last->inp_flags & INP_CONTROLOPTS ||
 692            last->inp_socket->so_options & SO_TIMESTAMP) {
 693#if INET6
 694                if (last->inp_vflag & INP_IPV6) {
 695                        int savedflags;
 696
 697                        if (udp_ip6.uip6_init_done == 0) {
 698                                ip_2_ip6_hdr(&udp_ip6.uip6_ip6, ip);
 699                                udp_ip6.uip6_init_done = 1;
 700                        }
 701                        savedflags = last->inp_flags;
 702                        last->inp_flags &= ~INP_UNMAPPABLEOPTS;
 703                        ip6_savecontrol(last, &opts, &udp_ip6.uip6_ip6, n);
 704                        last->inp_flags = savedflags;
 705                } else
 706#endif
 707                ip_savecontrol(last, &opts, ip, n);
 708        }
 709#if INET6
 710        if (last->inp_vflag & INP_IPV6) {
 711                if (udp_in6.uin6_init_done == 0) {
 712                        in6_sin_2_v4mapsin6(&udp_in, &udp_in6.uin6_sin);
 713                        udp_in6.uin6_init_done = 1;
 714                }
 715                append_sa = (struct sockaddr *)&udp_in6.uin6_sin;
 716        } else
 717#endif
 718        append_sa = (struct sockaddr *)&udp_in;
 719        m_adj(n, off);
 720        if (sbappendaddr(&last->inp_socket->so_rcv, append_sa, n, opts, NULL) == 0) {
 721                udpstat.udps_fullsock++;
 722        } else
 723                sorwakeup(last->inp_socket);
 724}
 725
 726/*
 727 * Notify a udp user of an asynchronous error;
 728 * just wake up so that he can collect error status.
 729 */
 730void
 731udp_notify(inp, errno)
 732        register struct inpcb *inp;
 733        int errno;
 734{
 735        inp->inp_socket->so_error = errno;
 736        sorwakeup(inp->inp_socket);
 737        sowwakeup(inp->inp_socket);
 738}
 739
 740void
 741udp_ctlinput(cmd, sa, vip)
 742        int cmd;
 743        struct sockaddr *sa;
 744        void *vip;
 745{
 746        struct ip *ip = vip;
 747        struct udphdr *uh;
 748        void (*notify)(struct inpcb *, int) = udp_notify;
 749        struct in_addr faddr;
 750        struct inpcb *inp;
 751
 752        faddr = ((struct sockaddr_in *)sa)->sin_addr;
 753        if (sa->sa_family != AF_INET || faddr.s_addr == INADDR_ANY)
 754                return;
 755
 756        if (PRC_IS_REDIRECT(cmd)) {
 757                ip = 0;
 758                notify = in_rtchange;
 759        } else if (cmd == PRC_HOSTDEAD)
 760                ip = 0;
 761        else if ((unsigned)cmd >= PRC_NCMDS || inetctlerrmap[cmd] == 0)
 762                return;
 763        if (ip) {
 764                uh = (struct udphdr *)((caddr_t)ip + (ip->ip_hl << 2));
 765                inp = in_pcblookup_hash(&udbinfo, faddr, uh->uh_dport,
 766                    ip->ip_src, uh->uh_sport, 0, NULL);
 767                if (inp != NULL && inp->inp_socket != NULL) {
 768                        udp_lock(inp->inp_socket, 1, 0);
 769                        if (in_pcb_checkstate(inp, WNT_RELEASE, 1) == WNT_STOPUSING)  {
 770                                udp_unlock(inp->inp_socket, 1, 0);
 771                                return;
 772                        }
 773                        (*notify)(inp, inetctlerrmap[cmd]);
 774                        udp_unlock(inp->inp_socket, 1, 0);
 775                }
 776        } else
 777                in_pcbnotifyall(&udbinfo, faddr, inetctlerrmap[cmd], notify);
 778}
 779
 780static int
 781udp_pcblist SYSCTL_HANDLER_ARGS
 782{
 783        int error, i, n;
 784        struct inpcb *inp, **inp_list;
 785        inp_gen_t gencnt;
 786        struct xinpgen xig;
 787
 788        /*
 789         * The process of preparing the TCB list is too time-consuming and
 790         * resource-intensive to repeat twice on every request.
 791         */
 792        lck_rw_lock_exclusive(udbinfo.mtx);
 793        if (req->oldptr == USER_ADDR_NULL) {
 794                n = udbinfo.ipi_count;
 795                req->oldidx = 2 * (sizeof xig)
 796                        + (n + n/8) * sizeof(struct xinpcb);
 797                lck_rw_done(udbinfo.mtx);
 798                return 0;
 799        }
 800
 801        if (req->newptr != USER_ADDR_NULL) {
 802                lck_rw_done(udbinfo.mtx);
 803                return EPERM;
 804        }
 805
 806        /*
 807         * OK, now we're committed to doing something.
 808         */
 809        gencnt = udbinfo.ipi_gencnt;
 810        n = udbinfo.ipi_count;
 811
 812        bzero(&xig, sizeof(xig));
 813        xig.xig_len = sizeof xig;
 814        xig.xig_count = n;
 815        xig.xig_gen = gencnt;
 816        xig.xig_sogen = so_gencnt;
 817        error = SYSCTL_OUT(req, &xig, sizeof xig);
 818        if (error) {
 819                lck_rw_done(udbinfo.mtx);
 820                return error;
 821        }
 822    /*
 823     * We are done if there is no pcb
 824     */
 825    if (n == 0) {
 826        lck_rw_done(udbinfo.mtx);
 827        return 0; 
 828    }
 829
 830        inp_list = _MALLOC(n * sizeof *inp_list, M_TEMP, M_WAITOK);
 831        if (inp_list == 0) {
 832                lck_rw_done(udbinfo.mtx);
 833                return ENOMEM;
 834        }
 835        
 836        for (inp = LIST_FIRST(udbinfo.listhead), i = 0; inp && i < n;
 837             inp = LIST_NEXT(inp, inp_list)) {
 838                if (inp->inp_gencnt <= gencnt && inp->inp_state != INPCB_STATE_DEAD)
 839                        inp_list[i++] = inp;
 840        }
 841        n = i;
 842
 843        error = 0;
 844        for (i = 0; i < n; i++) {
 845                inp = inp_list[i];
 846                if (inp->inp_gencnt <= gencnt && inp->inp_state != INPCB_STATE_DEAD) {
 847                        struct xinpcb xi;
 848
 849                        bzero(&xi, sizeof(xi));
 850                        xi.xi_len = sizeof xi;
 851                        /* XXX should avoid extra copy */
 852                        inpcb_to_compat(inp, &xi.xi_inp);
 853                        if (inp->inp_socket)
 854                                sotoxsocket(inp->inp_socket, &xi.xi_socket);
 855                        error = SYSCTL_OUT(req, &xi, sizeof xi);
 856                }
 857        }
 858        if (!error) {
 859                /*
 860                 * Give the user an updated idea of our state.
 861                 * If the generation differs from what we told
 862                 * her before, she knows that something happened
 863                 * while we were processing this request, and it
 864                 * might be necessary to retry.
 865                 */
 866                bzero(&xig, sizeof(xig));
 867                xig.xig_len = sizeof xig;
 868                xig.xig_gen = udbinfo.ipi_gencnt;
 869                xig.xig_sogen = so_gencnt;
 870                xig.xig_count = udbinfo.ipi_count;
 871                error = SYSCTL_OUT(req, &xig, sizeof xig);
 872        }
 873        FREE(inp_list, M_TEMP);
 874        lck_rw_done(udbinfo.mtx);
 875        return error;
 876}
 877
 878SYSCTL_PROC(_net_inet_udp, UDPCTL_PCBLIST, pcblist, CTLFLAG_RD, 0, 0,
 879            udp_pcblist, "S,xinpcb", "List of active UDP sockets");
 880
 881
 882
 883static __inline__ u_int16_t
 884get_socket_id(struct socket * s)
 885{
 886        u_int16_t               val;
 887
 888        if (s == NULL) {
 889            return (0);
 890        }
 891        val = (u_int16_t)(((u_int32_t)s) / sizeof(struct socket));
 892        if (val == 0) {
 893                val = 0xffff;
 894        }
 895        return (val);
 896}
 897
 898static int
 899udp_output(inp, m, addr, control, p)
 900        register struct inpcb *inp;
 901        struct mbuf *m;
 902        struct sockaddr *addr;
 903        struct mbuf *control;
 904        struct proc *p;
 905{
 906        register struct udpiphdr *ui;
 907        register int len = m->m_pkthdr.len;
 908        struct sockaddr_in *sin, src;
 909        struct in_addr origladdr, laddr, faddr;
 910        u_short lport, fport;
 911        struct sockaddr_in *ifaddr;
 912        int error = 0, udp_dodisconnect = 0;
 913
 914
 915        KERNEL_DEBUG(DBG_FNC_UDP_OUTPUT | DBG_FUNC_START, 0,0,0,0,0);
 916
 917        if (control)
 918                m_freem(control);               /* XXX */
 919
 920        KERNEL_DEBUG(DBG_LAYER_OUT_BEG, inp->inp_fport, inp->inp_lport,
 921                     inp->inp_laddr.s_addr, inp->inp_faddr.s_addr,
 922                     (htons((u_short)len + sizeof (struct udphdr))));
 923
 924        if (len + sizeof(struct udpiphdr) > IP_MAXPACKET) {
 925                error = EMSGSIZE;
 926                goto release;
 927        }
 928
 929        /* If there was a routing change, discard cached route and check
 930         * that we have a valid source address. 
 931         * Reacquire a new source address if INADDR_ANY was specified
 932         */
 933
 934#if 1
 935        lck_mtx_assert(inp->inpcb_mtx, LCK_MTX_ASSERT_OWNED);
 936#endif
 937
 938        if (inp->inp_route.ro_rt && inp->inp_route.ro_rt->generation_id != route_generation) {
 939                if (ifa_foraddr(inp->inp_laddr.s_addr) == 0) { /* src address is gone */
 940                        if (inp->inp_flags & INP_INADDR_ANY)
 941                                inp->inp_faddr.s_addr = INADDR_ANY; /* new src will be set later */
 942                        else {
 943                                error = EADDRNOTAVAIL;
 944                                goto release;
 945                        }
 946                }
 947                rtfree(inp->inp_route.ro_rt);
 948                inp->inp_route.ro_rt = (struct rtentry *)0;
 949        }
 950
 951        origladdr= laddr = inp->inp_laddr;
 952        faddr = inp->inp_faddr;
 953        lport = inp->inp_lport;
 954        fport = inp->inp_fport;
 955
 956        if (addr) {
 957                sin = (struct sockaddr_in *)addr;
 958                if (faddr.s_addr != INADDR_ANY) {
 959                        error = EISCONN;
 960                        goto release;
 961                }
 962                if (lport == 0) {
 963                        /*
 964                         * In case we don't have a local port set, go through the full connect.
 965                         * We don't have a local port yet (ie, we can't be looked up),
 966                         * so it's not an issue if the input runs at the same time we do this.
 967                         */
 968                        error = in_pcbconnect(inp, addr, p);
 969                        if (error) {
 970                                goto release;
 971                        }
 972                        laddr = inp->inp_laddr;
 973                        lport = inp->inp_lport;
 974                        faddr = inp->inp_faddr;
 975                        fport = inp->inp_fport;
 976                        udp_dodisconnect = 1;
 977                }
 978                else {  
 979                        /* Fast path case
 980                         * we have a full address and a local port.
 981                         * use those info to build the packet without changing the pcb
 982                         * and interfering with the input path. See 3851370
 983                         */
 984                        if (laddr.s_addr == INADDR_ANY) {
 985                           if ((error = in_pcbladdr(inp, addr, &ifaddr)) != 0)
 986                                   goto release;
 987                           laddr = ifaddr->sin_addr;
 988                           inp->inp_flags |= INP_INADDR_ANY; /* from pcbconnect: remember we don't care about src addr.*/
 989                        }
 990                                   
 991                        faddr = sin->sin_addr;
 992                        fport = sin->sin_port;
 993                }
 994        } else {
 995                if (faddr.s_addr == INADDR_ANY) {
 996                        error = ENOTCONN;
 997                        goto release;
 998                }
 999        }
1000
1001
1002        /*
1003         * Calculate data length and get a mbuf
1004         * for UDP and IP headers.
1005         */
1006        M_PREPEND(m, sizeof(struct udpiphdr), M_DONTWAIT);
1007        if (m == 0) {
1008                error = ENOBUFS;
1009                goto abort;
1010        }
1011
1012        /*
1013         * Fill in mbuf with extended UDP header
1014         * and addresses and length put into network format.
1015         */
1016        ui = mtod(m, struct udpiphdr *);
1017        bzero(ui->ui_x1, sizeof(ui->ui_x1));    /* XXX still needed? */
1018        ui->ui_pr = IPPROTO_UDP;
1019        ui->ui_src = laddr;
1020        ui->ui_dst = faddr;
1021        ui->ui_sport = lport;
1022        ui->ui_dport = fport;
1023        ui->ui_ulen = htons((u_short)len + sizeof(struct udphdr));
1024
1025        /*
1026         * Set up checksum and output datagram.
1027         */
1028        if (udpcksum) {
1029                ui->ui_sum = in_pseudo(ui->ui_src.s_addr, ui->ui_dst.s_addr,
1030                    htons((u_short)len + sizeof(struct udphdr) + IPPROTO_UDP));
1031                m->m_pkthdr.csum_flags = CSUM_UDP;
1032                m->m_pkthdr.csum_data = offsetof(struct udphdr, uh_sum);
1033        } else {
1034                ui->ui_sum = 0;
1035        }
1036        ((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len;
1037        ((struct ip *)ui)->ip_ttl = inp->inp_ip_ttl;    /* XXX */
1038        ((struct ip *)ui)->ip_tos = inp->inp_ip_tos;    /* XXX */
1039        udpstat.udps_opackets++;
1040
1041        KERNEL_DEBUG(DBG_LAYER_OUT_END, ui->ui_dport, ui->ui_sport,
1042                     ui->ui_src.s_addr, ui->ui_dst.s_addr, ui->ui_ulen);
1043
1044#if IPSEC
1045        if (ipsec_bypass == 0 && ipsec_setsocket(m, inp->inp_socket) != 0) {
1046                error = ENOBUFS;
1047                goto abort;
1048        }
1049#endif /*IPSEC*/
1050        m->m_pkthdr.socket_id = get_socket_id(inp->inp_socket);
1051        error = ip_output_list(m, 0,  inp->inp_options, &inp->inp_route,
1052            (inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST)),
1053            inp->inp_moptions);
1054
1055        if (udp_dodisconnect) {
1056                in_pcbdisconnect(inp);
1057                inp->inp_laddr = origladdr;     /* XXX rehash? */
1058        }
1059        KERNEL_DEBUG(DBG_FNC_UDP_OUTPUT | DBG_FUNC_END, error, 0,0,0,0);
1060        return (error);
1061
1062abort:
1063        if (udp_dodisconnect) {
1064                in_pcbdisconnect(inp);
1065                inp->inp_laddr = origladdr; /* XXX rehash? */
1066        }
1067
1068release:
1069        m_freem(m);
1070        KERNEL_DEBUG(DBG_FNC_UDP_OUTPUT | DBG_FUNC_END, error, 0,0,0,0);
1071        return (error);
1072}
1073
1074u_long  udp_sendspace = 9216;           /* really max datagram size */
1075                                        /* 40 1K datagrams */
1076SYSCTL_INT(_net_inet_udp, UDPCTL_MAXDGRAM, maxdgram, CTLFLAG_RW,
1077    &udp_sendspace, 0, "Maximum outgoing UDP datagram size");
1078
1079u_long  udp_recvspace = 40 * (1024 +
1080#if INET6
1081                                      sizeof(struct sockaddr_in6)
1082#else
1083                                      sizeof(struct sockaddr_in)
1084#endif
1085                                      );
1086SYSCTL_INT(_net_inet_udp, UDPCTL_RECVSPACE, recvspace, CTLFLAG_RW,
1087    &udp_recvspace, 0, "Maximum incoming UDP datagram size");
1088
1089static int
1090udp_abort(struct socket *so)
1091{
1092        struct inpcb *inp;
1093
1094        inp = sotoinpcb(so);
1095        if (inp == 0)
1096                panic("udp_abort: so=%x null inp\n", so);       /* ??? possible? panic instead? */
1097        soisdisconnected(so);
1098        in_pcbdetach(inp);
1099        return 0;
1100}
1101
1102static int
1103udp_attach(struct socket *so, int proto, struct proc *p)
1104{
1105        struct inpcb *inp;
1106        int error;
1107
1108        inp = sotoinpcb(so);
1109        if (inp != 0)
1110                panic ("udp_attach so=%x inp=%x\n", so, inp);
1111
1112        error = in_pcballoc(so, &udbinfo, p);
1113        if (error)
1114                return error;
1115        error = soreserve(so, udp_sendspace, udp_recvspace);
1116        if (error) 
1117                return error;
1118        inp = (struct inpcb *)so->so_pcb;
1119        inp->inp_vflag |= INP_IPV4;
1120        inp->inp_ip_ttl = ip_defttl;
1121        return 0;
1122}
1123
1124static int
1125udp_bind(struct socket *so, struct sockaddr *nam, struct proc *p)
1126{
1127        struct inpcb *inp;
1128        int error;
1129
1130        inp = sotoinpcb(so);
1131        if (inp == 0)
1132                return EINVAL;
1133        error = in_pcbbind(inp, nam, p);
1134        return error;
1135}
1136
1137static int
1138udp_connect(struct socket *so, struct sockaddr *nam, struct proc *p)
1139{
1140        struct inpcb *inp;
1141        int error;
1142
1143        inp = sotoinpcb(so);
1144        if (inp == 0)
1145                return EINVAL;
1146        if (inp->inp_faddr.s_addr != INADDR_ANY)
1147                return EISCONN;
1148        error = in_pcbconnect(inp, nam, p);
1149        if (error == 0) 
1150                soisconnected(so);
1151        return error;
1152}
1153
1154static int
1155udp_detach(struct socket *so)
1156{
1157        struct inpcb *inp;
1158
1159        inp = sotoinpcb(so);
1160        if (inp == 0)
1161                panic("udp_detach: so=%x null inp\n", so);      /* ??? possible? panic instead? */
1162        in_pcbdetach(inp);
1163        inp->inp_state = INPCB_STATE_DEAD;
1164        return 0;
1165}
1166
1167static int
1168udp_disconnect(struct socket *so)
1169{
1170        struct inpcb *inp;
1171
1172        inp = sotoinpcb(so);
1173        if (inp == 0)
1174                return EINVAL;
1175        if (inp->inp_faddr.s_addr == INADDR_ANY)
1176                return ENOTCONN;
1177
1178        in_pcbdisconnect(inp);
1179        inp->inp_laddr.s_addr = INADDR_ANY;
1180        so->so_state &= ~SS_ISCONNECTED;                /* XXX */
1181        return 0;
1182}
1183
1184static int
1185udp_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
1186            struct mbuf *control, struct proc *p)
1187{
1188        struct inpcb *inp;
1189
1190        inp = sotoinpcb(so);
1191        if (inp == 0) {
1192                m_freem(m);
1193                return EINVAL;
1194        }
1195        return udp_output(inp, m, addr, control, p);
1196}
1197
1198int
1199udp_shutdown(struct socket *so)
1200{
1201        struct inpcb *inp;
1202
1203        inp = sotoinpcb(so);
1204        if (inp == 0)
1205                return EINVAL;
1206        socantsendmore(so);
1207        return 0;
1208}
1209
1210struct pr_usrreqs udp_usrreqs = {
1211        udp_abort, pru_accept_notsupp, udp_attach, udp_bind, udp_connect, 
1212        pru_connect2_notsupp, in_control, udp_detach, udp_disconnect, 
1213        pru_listen_notsupp, in_setpeeraddr, pru_rcvd_notsupp, 
1214        pru_rcvoob_notsupp, udp_send, pru_sense_null, udp_shutdown,
1215        in_setsockaddr, sosend, soreceive, pru_sopoll_notsupp
1216};
1217
1218
1219int
1220udp_lock(so, refcount, debug)
1221        struct socket *so;
1222        int refcount, debug;
1223{
1224        int lr_saved;
1225#ifdef __ppc__
1226        if (debug == 0) {
1227                __asm__ volatile("mflr %0" : "=r" (lr_saved));
1228        }
1229        else lr_saved = debug;
1230#endif
1231
1232        if (so->so_pcb) {
1233                lck_mtx_assert(((struct inpcb *)so->so_pcb)->inpcb_mtx, LCK_MTX_ASSERT_NOTOWNED);
1234                lck_mtx_lock(((struct inpcb *)so->so_pcb)->inpcb_mtx);
1235        }
1236        else {
1237                panic("udp_lock: so=%x NO PCB! lr=%x\n", so, lr_saved);
1238                lck_mtx_assert(so->so_proto->pr_domain->dom_mtx, LCK_MTX_ASSERT_NOTOWNED);
1239                lck_mtx_lock(so->so_proto->pr_domain->dom_mtx);
1240        }
1241
1242        if (refcount) 
1243                so->so_usecount++;
1244
1245        so->reserved3= lr_saved;
1246        return (0);
1247}
1248
1249int
1250udp_unlock(so, refcount, debug)
1251        struct socket *so;
1252        int refcount;
1253        int debug;
1254{
1255        int lr_saved;
1256        struct inpcb *inp = sotoinpcb(so);
1257        struct inpcbinfo *pcbinfo       = &udbinfo;
1258#ifdef __ppc__
1259        if (debug == 0) {
1260                __asm__ volatile("mflr %0" : "=r" (lr_saved));
1261        }
1262        else lr_saved = debug;
1263#endif
1264        if (refcount) {
1265                so->so_usecount--;
1266#if 0
1267                if (so->so_usecount == 0 && (inp->inp_wantcnt == WNT_STOPUSING)) {
1268                        if (lck_rw_try_lock_exclusive(pcbinfo->mtx)) {
1269                                in_pcbdispose(inp);
1270                                lck_rw_done(pcbinfo->mtx);
1271                                return(0);
1272                        }
1273                }
1274#endif
1275        }
1276        if (so->so_pcb == NULL) {
1277                panic("udp_unlock: so=%x NO PCB! lr=%x\n", so, lr_saved);
1278                lck_mtx_assert(so->so_proto->pr_domain->dom_mtx, LCK_MTX_ASSERT_OWNED);
1279                lck_mtx_unlock(so->so_proto->pr_domain->dom_mtx);
1280        }
1281        else {
1282                lck_mtx_assert(((struct inpcb *)so->so_pcb)->inpcb_mtx, LCK_MTX_ASSERT_OWNED);
1283                lck_mtx_unlock(((struct inpcb *)so->so_pcb)->inpcb_mtx);
1284        }
1285
1286
1287        so->reserved4 = lr_saved;
1288        return (0);
1289}
1290
1291lck_mtx_t *
1292udp_getlock(so, locktype)
1293        struct socket *so;
1294        int locktype;
1295{
1296        struct inpcb *inp = sotoinpcb(so);
1297
1298
1299        if (so->so_pcb)
1300                return(inp->inpcb_mtx);
1301        else {
1302                panic("udp_getlock: so=%x NULL so_pcb\n", so);
1303                return (so->so_proto->pr_domain->dom_mtx);
1304        }
1305}
1306
1307void
1308udp_slowtimo()
1309{
1310        struct inpcb *inp, *inpnxt;
1311        struct socket *so;
1312        struct inpcbinfo *pcbinfo       = &udbinfo;
1313
1314        lck_rw_lock_exclusive(pcbinfo->mtx);
1315
1316        for (inp = udb.lh_first; inp != NULL; inp = inpnxt) {
1317                inpnxt = inp->inp_list.le_next;
1318        
1319                /* Ignore nat/SharedIP dummy pcbs */
1320                if (inp->inp_socket == &udbinfo.nat_dummy_socket)
1321                                continue;
1322
1323                if (inp->inp_wantcnt != WNT_STOPUSING) 
1324                        continue;
1325
1326                so = inp->inp_socket;
1327                if (!lck_mtx_try_lock(inp->inpcb_mtx))  /* skip if busy, no hurry for cleanup... */
1328                        continue;
1329
1330                if (so->so_usecount == 0)
1331                        in_pcbdispose(inp);
1332                else 
1333                        lck_mtx_unlock(inp->inpcb_mtx);
1334        }
1335        lck_rw_done(pcbinfo->mtx);
1336}
1337
1338int
1339ChkAddressOK( __uint32_t dstaddr, __uint32_t srcaddr )
1340{
1341        if ( dstaddr == srcaddr ){
1342                return 0;
1343        }
1344        return 1;
1345}
1346
1347
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.