raw_ip.c revision 167739
1292588Sdelphij/*- 2274261Sdelphij * Copyright (c) 1982, 1986, 1988, 1993 3292588Sdelphij * The Regents of the University of California. All rights reserved. 4274261Sdelphij * 5292588Sdelphij * Redistribution and use in source and binary forms, with or without 6274261Sdelphij * modification, are permitted provided that the following conditions 7274261Sdelphij * are met: 8274261Sdelphij * 1. Redistributions of source code must retain the above copyright 9274261Sdelphij * notice, this list of conditions and the following disclaimer. 10274261Sdelphij * 2. Redistributions in binary form must reproduce the above copyright 11292588Sdelphij * notice, this list of conditions and the following disclaimer in the 12274261Sdelphij * documentation and/or other materials provided with the distribution. 13292588Sdelphij * 4. Neither the name of the University nor the names of its contributors 14274261Sdelphij * may be used to endorse or promote products derived from this software 15292588Sdelphij * without specific prior written permission. 16274261Sdelphij * 17292588Sdelphij * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18292588Sdelphij * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19274261Sdelphij * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20292588Sdelphij * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21292588Sdelphij * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22292588Sdelphij * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23292588Sdelphij * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24292588Sdelphij * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25292588Sdelphij * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26292588Sdelphij * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27292588Sdelphij * SUCH DAMAGE. 28292588Sdelphij * 29292588Sdelphij * @(#)raw_ip.c 8.7 (Berkeley) 5/15/95 30292588Sdelphij * $FreeBSD: head/sys/netinet/raw_ip.c 167739 2007-03-20 13:15:20Z bms $ 31292588Sdelphij */ 32292588Sdelphij 33292588Sdelphij#include "opt_inet6.h" 34292588Sdelphij#include "opt_ipsec.h" 35292588Sdelphij#include "opt_mac.h" 36292588Sdelphij 37292588Sdelphij#include <sys/param.h> 38292588Sdelphij#include <sys/jail.h> 39292588Sdelphij#include <sys/kernel.h> 40292588Sdelphij#include <sys/lock.h> 41292588Sdelphij#include <sys/malloc.h> 42292588Sdelphij#include <sys/mbuf.h> 43292588Sdelphij#include <sys/priv.h> 44292588Sdelphij#include <sys/proc.h> 45292588Sdelphij#include <sys/protosw.h> 46292588Sdelphij#include <sys/signalvar.h> 47292588Sdelphij#include <sys/socket.h> 48292588Sdelphij#include <sys/socketvar.h> 49292588Sdelphij#include <sys/sx.h> 50292588Sdelphij#include <sys/sysctl.h> 51292588Sdelphij#include <sys/systm.h> 52292588Sdelphij 53292588Sdelphij#include <vm/uma.h> 54292588Sdelphij 55292588Sdelphij#include <net/if.h> 56292588Sdelphij#include <net/route.h> 57292588Sdelphij 58292588Sdelphij#include <netinet/in.h> 59292588Sdelphij#include <netinet/in_systm.h> 60292588Sdelphij#include <netinet/in_pcb.h> 61292588Sdelphij#include <netinet/in_var.h> 62292588Sdelphij#include <netinet/ip.h> 63292588Sdelphij#include <netinet/ip_var.h> 64274261Sdelphij#include <netinet/ip_mroute.h> 65292588Sdelphij 66274261Sdelphij#include <netinet/ip_fw.h> 67292588Sdelphij#include <netinet/ip_dummynet.h> 68292588Sdelphij 69292588Sdelphij#ifdef FAST_IPSEC 70292588Sdelphij#include <netipsec/ipsec.h> 71274261Sdelphij#endif /*FAST_IPSEC*/ 72292588Sdelphij 73292588Sdelphij#ifdef IPSEC 74292588Sdelphij#include <netinet6/ipsec.h> 75292588Sdelphij#endif /*IPSEC*/ 76292588Sdelphij 77292588Sdelphij#include <security/mac/mac_framework.h> 78292588Sdelphij 79292588Sdelphijstruct inpcbhead ripcb; 80292588Sdelphijstruct inpcbinfo ripcbinfo; 81292588Sdelphij 82292588Sdelphij/* control hooks for ipfw and dummynet */ 83292588Sdelphijip_fw_ctl_t *ip_fw_ctl_ptr = NULL; 84292588Sdelphijip_dn_ctl_t *ip_dn_ctl_ptr = NULL; 85292588Sdelphij 86292588Sdelphij/* 87292588Sdelphij * hooks for multicast routing. They all default to NULL, 88292588Sdelphij * so leave them not initialized and rely on BSS being set to 0. 89292588Sdelphij */ 90292588Sdelphij 91292588Sdelphij/* The socket used to communicate with the multicast routing daemon. */ 92292588Sdelphijstruct socket *ip_mrouter; 93292588Sdelphij 94292588Sdelphij/* The various mrouter and rsvp functions */ 95292588Sdelphijint (*ip_mrouter_set)(struct socket *, struct sockopt *); 96292588Sdelphijint (*ip_mrouter_get)(struct socket *, struct sockopt *); 97292588Sdelphijint (*ip_mrouter_done)(void); 98292588Sdelphijint (*ip_mforward)(struct ip *, struct ifnet *, struct mbuf *, 99292588Sdelphij struct ip_moptions *); 100292588Sdelphijint (*mrt_ioctl)(int, caddr_t); 101292588Sdelphijint (*legal_vif_num)(int); 102292588Sdelphiju_long (*ip_mcast_src)(int); 103292588Sdelphij 104292588Sdelphijvoid (*rsvp_input_p)(struct mbuf *m, int off); 105292588Sdelphijint (*ip_rsvp_vif)(struct socket *, struct sockopt *); 106292588Sdelphijvoid (*ip_rsvp_force_done)(struct socket *); 107292588Sdelphij 108292588Sdelphij/* 109292588Sdelphij * Raw interface to IP protocol. 110292588Sdelphij */ 111292588Sdelphij 112292588Sdelphij/* 113292588Sdelphij * Initialize raw connection block q. 114292588Sdelphij */ 115292588Sdelphijstatic void 116292588Sdelphijrip_zone_change(void *tag) 117292588Sdelphij{ 118292588Sdelphij 119292588Sdelphij uma_zone_set_max(ripcbinfo.ipi_zone, maxsockets); 120292588Sdelphij} 121292588Sdelphij 122292588Sdelphijstatic int 123292588Sdelphijrip_inpcb_init(void *mem, int size, int flags) 124292588Sdelphij{ 125292588Sdelphij struct inpcb *inp = mem; 126292588Sdelphij 127292588Sdelphij INP_LOCK_INIT(inp, "inp", "rawinp"); 128292588Sdelphij return (0); 129292588Sdelphij} 130292588Sdelphij 131292588Sdelphijvoid 132292588Sdelphijrip_init() 133292588Sdelphij{ 134292588Sdelphij INP_INFO_LOCK_INIT(&ripcbinfo, "rip"); 135292588Sdelphij LIST_INIT(&ripcb); 136292588Sdelphij ripcbinfo.listhead = &ripcb; 137292588Sdelphij /* 138292588Sdelphij * XXX We don't use the hash list for raw IP, but it's easier 139292588Sdelphij * to allocate a one entry hash list than it is to check all 140292588Sdelphij * over the place for hashbase == NULL. 141292588Sdelphij */ 142292588Sdelphij ripcbinfo.hashbase = hashinit(1, M_PCB, &ripcbinfo.hashmask); 143292588Sdelphij ripcbinfo.porthashbase = hashinit(1, M_PCB, &ripcbinfo.porthashmask); 144292588Sdelphij ripcbinfo.ipi_zone = uma_zcreate("ripcb", sizeof(struct inpcb), 145292588Sdelphij NULL, NULL, rip_inpcb_init, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE); 146292588Sdelphij uma_zone_set_max(ripcbinfo.ipi_zone, maxsockets); 147292588Sdelphij EVENTHANDLER_REGISTER(maxsockets_change, rip_zone_change, 148292588Sdelphij NULL, EVENTHANDLER_PRI_ANY); 149292588Sdelphij} 150292588Sdelphij 151292588Sdelphijstatic struct sockaddr_in ripsrc = { sizeof(ripsrc), AF_INET }; 152292588Sdelphij 153292588Sdelphijstatic int 154292588Sdelphijraw_append(struct inpcb *last, struct ip *ip, struct mbuf *n) 155292588Sdelphij{ 156292588Sdelphij int policyfail = 0; 157292588Sdelphij 158292588Sdelphij INP_LOCK_ASSERT(last); 159292588Sdelphij 160292588Sdelphij#if defined(IPSEC) || defined(FAST_IPSEC) 161292588Sdelphij /* check AH/ESP integrity. */ 162292588Sdelphij if (ipsec4_in_reject(n, last)) { 163292588Sdelphij policyfail = 1; 164292588Sdelphij#ifdef IPSEC 165292588Sdelphij ipsecstat.in_polvio++; 166292588Sdelphij#endif /*IPSEC*/ 167292588Sdelphij /* do not inject data to pcb */ 168292588Sdelphij } 169292588Sdelphij#endif /*IPSEC || FAST_IPSEC*/ 170292588Sdelphij#ifdef MAC 171292588Sdelphij if (!policyfail && mac_check_inpcb_deliver(last, n) != 0) 172292588Sdelphij policyfail = 1; 173292588Sdelphij#endif 174292588Sdelphij /* Check the minimum TTL for socket. */ 175292588Sdelphij if (last->inp_ip_minttl && last->inp_ip_minttl > ip->ip_ttl) 176292588Sdelphij policyfail = 1; 177292588Sdelphij if (!policyfail) { 178292588Sdelphij struct mbuf *opts = NULL; 179292588Sdelphij struct socket *so; 180292588Sdelphij 181292588Sdelphij so = last->inp_socket; 182292588Sdelphij if ((last->inp_flags & INP_CONTROLOPTS) || 183292588Sdelphij (so->so_options & (SO_TIMESTAMP | SO_BINTIME))) 184292588Sdelphij ip_savecontrol(last, &opts, ip, n); 185292588Sdelphij SOCKBUF_LOCK(&so->so_rcv); 186292588Sdelphij if (sbappendaddr_locked(&so->so_rcv, 187292588Sdelphij (struct sockaddr *)&ripsrc, n, opts) == 0) { 188292588Sdelphij /* should notify about lost packet */ 189292588Sdelphij m_freem(n); 190292588Sdelphij if (opts) 191292588Sdelphij m_freem(opts); 192292588Sdelphij SOCKBUF_UNLOCK(&so->so_rcv); 193292588Sdelphij } else 194292588Sdelphij sorwakeup_locked(so); 195292588Sdelphij } else 196292588Sdelphij m_freem(n); 197292588Sdelphij return policyfail; 198292588Sdelphij} 199292588Sdelphij 200292588Sdelphij/* 201292588Sdelphij * Setup generic address and protocol structures 202292588Sdelphij * for raw_input routine, then pass them along with 203292588Sdelphij * mbuf chain. 204292588Sdelphij */ 205292588Sdelphijvoid 206292588Sdelphijrip_input(struct mbuf *m, int off) 207292588Sdelphij{ 208292588Sdelphij struct ip *ip = mtod(m, struct ip *); 209292588Sdelphij int proto = ip->ip_p; 210292588Sdelphij struct inpcb *inp, *last; 211292588Sdelphij 212292588Sdelphij INP_INFO_RLOCK(&ripcbinfo); 213292588Sdelphij ripsrc.sin_addr = ip->ip_src; 214292588Sdelphij last = NULL; 215292588Sdelphij LIST_FOREACH(inp, &ripcb, inp_list) { 216292588Sdelphij INP_LOCK(inp); 217292588Sdelphij if (inp->inp_ip_p && inp->inp_ip_p != proto) { 218292588Sdelphij docontinue: 219292588Sdelphij INP_UNLOCK(inp); 220292588Sdelphij continue; 221292588Sdelphij } 222292588Sdelphij#ifdef INET6 223292588Sdelphij if ((inp->inp_vflag & INP_IPV4) == 0) 224292588Sdelphij goto docontinue; 225292588Sdelphij#endif 226292588Sdelphij if (inp->inp_laddr.s_addr && 227292588Sdelphij inp->inp_laddr.s_addr != ip->ip_dst.s_addr) 228292588Sdelphij goto docontinue; 229292588Sdelphij if (inp->inp_faddr.s_addr && 230292588Sdelphij inp->inp_faddr.s_addr != ip->ip_src.s_addr) 231292588Sdelphij goto docontinue; 232292588Sdelphij if (jailed(inp->inp_socket->so_cred)) 233292588Sdelphij if (htonl(prison_getip(inp->inp_socket->so_cred)) != 234292588Sdelphij ip->ip_dst.s_addr) 235292588Sdelphij goto docontinue; 236292588Sdelphij if (last) { 237292588Sdelphij struct mbuf *n; 238292588Sdelphij 239292588Sdelphij n = m_copy(m, 0, (int)M_COPYALL); 240292588Sdelphij if (n != NULL) 241292588Sdelphij (void) raw_append(last, ip, n); 242292588Sdelphij /* XXX count dropped packet */ 243292588Sdelphij INP_UNLOCK(last); 244292588Sdelphij } 245292588Sdelphij last = inp; 246292588Sdelphij } 247292588Sdelphij if (last != NULL) { 248292588Sdelphij if (raw_append(last, ip, m) != 0) 249292588Sdelphij ipstat.ips_delivered--; 250292588Sdelphij INP_UNLOCK(last); 251292588Sdelphij } else { 252292588Sdelphij m_freem(m); 253292588Sdelphij ipstat.ips_noproto++; 254292588Sdelphij ipstat.ips_delivered--; 255292588Sdelphij } 256292588Sdelphij INP_INFO_RUNLOCK(&ripcbinfo); 257292588Sdelphij} 258292588Sdelphij 259292588Sdelphij/* 260292588Sdelphij * Generate IP header and pass packet to ip_output. 261292588Sdelphij * Tack on options user may have setup with control call. 262292588Sdelphij */ 263292588Sdelphijint 264292588Sdelphijrip_output(struct mbuf *m, struct socket *so, u_long dst) 265292588Sdelphij{ 266292588Sdelphij struct ip *ip; 267292588Sdelphij int error; 268292588Sdelphij struct inpcb *inp = sotoinpcb(so); 269292588Sdelphij int flags = ((so->so_options & SO_DONTROUTE) ? IP_ROUTETOIF : 0) | 270292588Sdelphij IP_ALLOWBROADCAST; 271292588Sdelphij 272292588Sdelphij /* 273292588Sdelphij * If the user handed us a complete IP packet, use it. 274292588Sdelphij * Otherwise, allocate an mbuf for a header and fill it in. 275292588Sdelphij */ 276292588Sdelphij if ((inp->inp_flags & INP_HDRINCL) == 0) { 277292588Sdelphij if (m->m_pkthdr.len + sizeof(struct ip) > IP_MAXPACKET) { 278292588Sdelphij m_freem(m); 279292588Sdelphij return(EMSGSIZE); 280292588Sdelphij } 281292588Sdelphij M_PREPEND(m, sizeof(struct ip), M_DONTWAIT); 282292588Sdelphij if (m == NULL) 283292588Sdelphij return(ENOBUFS); 284292588Sdelphij 285292588Sdelphij INP_LOCK(inp); 286292588Sdelphij ip = mtod(m, struct ip *); 287292588Sdelphij ip->ip_tos = inp->inp_ip_tos; 288292588Sdelphij if (inp->inp_flags & INP_DONTFRAG) 289292588Sdelphij ip->ip_off = IP_DF; 290292588Sdelphij else 291292588Sdelphij ip->ip_off = 0; 292292588Sdelphij ip->ip_p = inp->inp_ip_p; 293292588Sdelphij ip->ip_len = m->m_pkthdr.len; 294292588Sdelphij if (jailed(inp->inp_socket->so_cred)) 295292588Sdelphij ip->ip_src.s_addr = 296292588Sdelphij htonl(prison_getip(inp->inp_socket->so_cred)); 297292588Sdelphij else 298292588Sdelphij ip->ip_src = inp->inp_laddr; 299292588Sdelphij ip->ip_dst.s_addr = dst; 300292588Sdelphij ip->ip_ttl = inp->inp_ip_ttl; 301292588Sdelphij } else { 302292588Sdelphij if (m->m_pkthdr.len > IP_MAXPACKET) { 303292588Sdelphij m_freem(m); 304292588Sdelphij return(EMSGSIZE); 305292588Sdelphij } 306292588Sdelphij INP_LOCK(inp); 307292588Sdelphij ip = mtod(m, struct ip *); 308292588Sdelphij if (jailed(inp->inp_socket->so_cred)) { 309274261Sdelphij if (ip->ip_src.s_addr != 310274261Sdelphij htonl(prison_getip(inp->inp_socket->so_cred))) { 311292588Sdelphij INP_UNLOCK(inp); 312274261Sdelphij m_freem(m); 313292588Sdelphij return (EPERM); 314292588Sdelphij } 315292588Sdelphij } 316292588Sdelphij /* don't allow both user specified and setsockopt options, 317292588Sdelphij and don't allow packet length sizes that will crash */ 318292588Sdelphij if (((ip->ip_hl != (sizeof (*ip) >> 2)) 319292588Sdelphij && inp->inp_options) 320292588Sdelphij || (ip->ip_len > m->m_pkthdr.len) 321292588Sdelphij || (ip->ip_len < (ip->ip_hl << 2))) { 322292588Sdelphij INP_UNLOCK(inp); 323292588Sdelphij m_freem(m); 324292588Sdelphij return EINVAL; 325292588Sdelphij } 326292588Sdelphij if (ip->ip_id == 0) 327292588Sdelphij ip->ip_id = ip_newid(); 328292588Sdelphij /* XXX prevent ip_output from overwriting header fields */ 329292588Sdelphij flags |= IP_RAWOUTPUT; 330292588Sdelphij ipstat.ips_rawout++; 331292588Sdelphij } 332292588Sdelphij 333292588Sdelphij if (inp->inp_flags & INP_ONESBCAST) 334292588Sdelphij flags |= IP_SENDONES; 335292588Sdelphij 336292588Sdelphij#ifdef MAC 337292588Sdelphij mac_create_mbuf_from_inpcb(inp, m); 338292588Sdelphij#endif 339292588Sdelphij 340292588Sdelphij error = ip_output(m, inp->inp_options, NULL, flags, 341292588Sdelphij inp->inp_moptions, inp); 342292588Sdelphij INP_UNLOCK(inp); 343292588Sdelphij return error; 344292588Sdelphij} 345292588Sdelphij 346292588Sdelphij/* 347292588Sdelphij * Raw IP socket option processing. 348292588Sdelphij * 349292588Sdelphij * IMPORTANT NOTE regarding access control: Traditionally, raw sockets could 350292588Sdelphij * only be created by a privileged process, and as such, socket option 351292588Sdelphij * operations to manage system properties on any raw socket were allowed to 352292588Sdelphij * take place without explicit additional access control checks. However, 353292588Sdelphij * raw sockets can now also be created in jail(), and therefore explicit 354292588Sdelphij * checks are now required. Likewise, raw sockets can be used by a process 355292588Sdelphij * after it gives up privilege, so some caution is required. For options 356292588Sdelphij * passed down to the IP layer via ip_ctloutput(), checks are assumed to be 357292588Sdelphij * performed in ip_ctloutput() and therefore no check occurs here. 358292588Sdelphij * Unilaterally checking suser() here breaks normal IP socket option 359292588Sdelphij * operations on raw sockets. 360292588Sdelphij * 361292588Sdelphij * When adding new socket options here, make sure to add access control 362292588Sdelphij * checks here as necessary. 363292588Sdelphij */ 364292588Sdelphijint 365292588Sdelphijrip_ctloutput(struct socket *so, struct sockopt *sopt) 366292588Sdelphij{ 367292588Sdelphij struct inpcb *inp = sotoinpcb(so); 368292588Sdelphij int error, optval; 369292588Sdelphij 370292588Sdelphij if (sopt->sopt_level != IPPROTO_IP) 371292588Sdelphij return (EINVAL); 372292588Sdelphij 373292588Sdelphij error = 0; 374292588Sdelphij switch (sopt->sopt_dir) { 375292588Sdelphij case SOPT_GET: 376292588Sdelphij switch (sopt->sopt_name) { 377292588Sdelphij case IP_HDRINCL: 378292588Sdelphij optval = inp->inp_flags & INP_HDRINCL; 379292588Sdelphij error = sooptcopyout(sopt, &optval, sizeof optval); 380292588Sdelphij break; 381292588Sdelphij 382292588Sdelphij case IP_FW_ADD: /* ADD actually returns the body... */ 383292588Sdelphij case IP_FW_GET: 384292588Sdelphij case IP_FW_TABLE_GETSIZE: 385292588Sdelphij case IP_FW_TABLE_LIST: 386292588Sdelphij case IP_FW_NAT_GET_CONFIG: 387292588Sdelphij case IP_FW_NAT_GET_LOG: 388292588Sdelphij /* 389292588Sdelphij * XXXRW: Isn't this checked one layer down? Yes, it 390292588Sdelphij * is. 391292588Sdelphij */ 392292588Sdelphij error = priv_check(curthread, PRIV_NETINET_IPFW); 393292588Sdelphij if (error != 0) 394292588Sdelphij return (error); 395292588Sdelphij if (ip_fw_ctl_ptr != NULL) 396292588Sdelphij error = ip_fw_ctl_ptr(sopt); 397292588Sdelphij else 398292588Sdelphij error = ENOPROTOOPT; 399292588Sdelphij break; 400292588Sdelphij 401292588Sdelphij case IP_DUMMYNET_GET: 402292588Sdelphij error = priv_check(curthread, PRIV_NETINET_DUMMYNET); 403292588Sdelphij if (error != 0) 404292588Sdelphij return (error); 405292588Sdelphij if (ip_dn_ctl_ptr != NULL) 406292588Sdelphij error = ip_dn_ctl_ptr(sopt); 407292588Sdelphij else 408292588Sdelphij error = ENOPROTOOPT; 409292588Sdelphij break ; 410292588Sdelphij 411292588Sdelphij case MRT_INIT: 412292588Sdelphij case MRT_DONE: 413292588Sdelphij case MRT_ADD_VIF: 414292588Sdelphij case MRT_DEL_VIF: 415292588Sdelphij case MRT_ADD_MFC: 416292588Sdelphij case MRT_DEL_MFC: 417292588Sdelphij case MRT_VERSION: 418292588Sdelphij case MRT_ASSERT: 419292588Sdelphij case MRT_API_SUPPORT: 420292588Sdelphij case MRT_API_CONFIG: 421292588Sdelphij case MRT_ADD_BW_UPCALL: 422292588Sdelphij case MRT_DEL_BW_UPCALL: 423292588Sdelphij error = priv_check(curthread, PRIV_NETINET_MROUTE); 424292588Sdelphij if (error != 0) 425292588Sdelphij return (error); 426292588Sdelphij error = ip_mrouter_get ? ip_mrouter_get(so, sopt) : 427292588Sdelphij EOPNOTSUPP; 428292588Sdelphij break; 429292588Sdelphij 430292588Sdelphij default: 431292588Sdelphij error = ip_ctloutput(so, sopt); 432292588Sdelphij break; 433292588Sdelphij } 434292588Sdelphij break; 435292588Sdelphij 436292588Sdelphij case SOPT_SET: 437292588Sdelphij switch (sopt->sopt_name) { 438292588Sdelphij case IP_HDRINCL: 439292588Sdelphij error = sooptcopyin(sopt, &optval, sizeof optval, 440292588Sdelphij sizeof optval); 441292588Sdelphij if (error) 442292588Sdelphij break; 443292588Sdelphij if (optval) 444292588Sdelphij inp->inp_flags |= INP_HDRINCL; 445292588Sdelphij else 446292588Sdelphij inp->inp_flags &= ~INP_HDRINCL; 447292588Sdelphij break; 448292588Sdelphij 449292588Sdelphij case IP_FW_ADD: 450292588Sdelphij case IP_FW_DEL: 451292588Sdelphij case IP_FW_FLUSH: 452292588Sdelphij case IP_FW_ZERO: 453292588Sdelphij case IP_FW_RESETLOG: 454292588Sdelphij case IP_FW_TABLE_ADD: 455292588Sdelphij case IP_FW_TABLE_DEL: 456292588Sdelphij case IP_FW_TABLE_FLUSH: 457292588Sdelphij case IP_FW_NAT_CFG: 458292588Sdelphij case IP_FW_NAT_DEL: 459292588Sdelphij /* 460292588Sdelphij * XXXRW: Isn't this checked one layer down? 461292588Sdelphij */ 462292588Sdelphij error = priv_check(curthread, PRIV_NETINET_IPFW); 463292588Sdelphij if (error != 0) 464292588Sdelphij return (error); 465292588Sdelphij if (ip_fw_ctl_ptr != NULL) 466292588Sdelphij error = ip_fw_ctl_ptr(sopt); 467292588Sdelphij else 468292588Sdelphij error = ENOPROTOOPT; 469292588Sdelphij break; 470292588Sdelphij 471292588Sdelphij case IP_DUMMYNET_CONFIGURE: 472292588Sdelphij case IP_DUMMYNET_DEL: 473292588Sdelphij case IP_DUMMYNET_FLUSH: 474292588Sdelphij error = priv_check(curthread, PRIV_NETINET_DUMMYNET); 475292588Sdelphij if (error != 0) 476292588Sdelphij return (error); 477292588Sdelphij if (ip_dn_ctl_ptr != NULL) 478292588Sdelphij error = ip_dn_ctl_ptr(sopt); 479292588Sdelphij else 480292588Sdelphij error = ENOPROTOOPT ; 481292588Sdelphij break ; 482292588Sdelphij 483292588Sdelphij case IP_RSVP_ON: 484292588Sdelphij error = priv_check(curthread, PRIV_NETINET_MROUTE); 485292588Sdelphij if (error != 0) 486292588Sdelphij return (error); 487292588Sdelphij error = ip_rsvp_init(so); 488292588Sdelphij break; 489292588Sdelphij 490292588Sdelphij case IP_RSVP_OFF: 491292588Sdelphij error = priv_check(curthread, PRIV_NETINET_MROUTE); 492292588Sdelphij if (error != 0) 493292588Sdelphij return (error); 494292588Sdelphij error = ip_rsvp_done(); 495292588Sdelphij break; 496292588Sdelphij 497292588Sdelphij case IP_RSVP_VIF_ON: 498292588Sdelphij case IP_RSVP_VIF_OFF: 499292588Sdelphij error = priv_check(curthread, PRIV_NETINET_MROUTE); 500292588Sdelphij if (error != 0) 501292588Sdelphij return (error); 502292588Sdelphij error = ip_rsvp_vif ? 503292588Sdelphij ip_rsvp_vif(so, sopt) : EINVAL; 504292588Sdelphij break; 505292588Sdelphij 506292588Sdelphij case MRT_INIT: 507292588Sdelphij case MRT_DONE: 508292588Sdelphij case MRT_ADD_VIF: 509292588Sdelphij case MRT_DEL_VIF: 510292588Sdelphij case MRT_ADD_MFC: 511292588Sdelphij case MRT_DEL_MFC: 512292588Sdelphij case MRT_VERSION: 513292588Sdelphij case MRT_ASSERT: 514292588Sdelphij case MRT_API_SUPPORT: 515292588Sdelphij case MRT_API_CONFIG: 516292588Sdelphij case MRT_ADD_BW_UPCALL: 517292588Sdelphij case MRT_DEL_BW_UPCALL: 518292588Sdelphij error = priv_check(curthread, PRIV_NETINET_MROUTE); 519292588Sdelphij if (error != 0) 520292588Sdelphij return (error); 521292588Sdelphij error = ip_mrouter_set ? ip_mrouter_set(so, sopt) : 522292588Sdelphij EOPNOTSUPP; 523292588Sdelphij break; 524292588Sdelphij 525292588Sdelphij default: 526292588Sdelphij error = ip_ctloutput(so, sopt); 527292588Sdelphij break; 528292588Sdelphij } 529292588Sdelphij break; 530292588Sdelphij } 531292588Sdelphij 532292588Sdelphij return (error); 533292588Sdelphij} 534292588Sdelphij 535292588Sdelphij/* 536292588Sdelphij * This function exists solely to receive the PRC_IFDOWN messages which 537292588Sdelphij * are sent by if_down(). It looks for an ifaddr whose ifa_addr is sa, 538292588Sdelphij * and calls in_ifadown() to remove all routes corresponding to that address. 539292588Sdelphij * It also receives the PRC_IFUP messages from if_up() and reinstalls the 540292588Sdelphij * interface routes. 541292588Sdelphij */ 542292588Sdelphijvoid 543292588Sdelphijrip_ctlinput(int cmd, struct sockaddr *sa, void *vip) 544292588Sdelphij{ 545292588Sdelphij struct in_ifaddr *ia; 546292588Sdelphij struct ifnet *ifp; 547292588Sdelphij int err; 548292588Sdelphij int flags; 549292588Sdelphij 550292588Sdelphij switch (cmd) { 551292588Sdelphij case PRC_IFDOWN: 552292588Sdelphij TAILQ_FOREACH(ia, &in_ifaddrhead, ia_link) { 553292588Sdelphij if (ia->ia_ifa.ifa_addr == sa 554292588Sdelphij && (ia->ia_flags & IFA_ROUTE)) { 555292588Sdelphij /* 556292588Sdelphij * in_ifscrub kills the interface route. 557292588Sdelphij */ 558292588Sdelphij in_ifscrub(ia->ia_ifp, ia); 559292588Sdelphij /* 560292588Sdelphij * in_ifadown gets rid of all the rest of 561292588Sdelphij * the routes. This is not quite the right 562292588Sdelphij * thing to do, but at least if we are running 563292588Sdelphij * a routing process they will come back. 564292588Sdelphij */ 565292588Sdelphij in_ifadown(&ia->ia_ifa, 0); 566292588Sdelphij break; 567292588Sdelphij } 568292588Sdelphij } 569292588Sdelphij break; 570292588Sdelphij 571292588Sdelphij case PRC_IFUP: 572292588Sdelphij TAILQ_FOREACH(ia, &in_ifaddrhead, ia_link) { 573292588Sdelphij if (ia->ia_ifa.ifa_addr == sa) 574292588Sdelphij break; 575292588Sdelphij } 576292588Sdelphij if (ia == 0 || (ia->ia_flags & IFA_ROUTE)) 577292588Sdelphij return; 578292588Sdelphij flags = RTF_UP; 579292588Sdelphij ifp = ia->ia_ifa.ifa_ifp; 580292588Sdelphij 581292588Sdelphij if ((ifp->if_flags & IFF_LOOPBACK) 582292588Sdelphij || (ifp->if_flags & IFF_POINTOPOINT)) 583292588Sdelphij flags |= RTF_HOST; 584292588Sdelphij 585292588Sdelphij err = rtinit(&ia->ia_ifa, RTM_ADD, flags); 586292588Sdelphij if (err == 0) 587292588Sdelphij ia->ia_flags |= IFA_ROUTE; 588292588Sdelphij break; 589292588Sdelphij } 590292588Sdelphij} 591292588Sdelphij 592292588Sdelphiju_long rip_sendspace = 9216; 593292588Sdelphiju_long rip_recvspace = 9216; 594292588Sdelphij 595292588SdelphijSYSCTL_ULONG(_net_inet_raw, OID_AUTO, maxdgram, CTLFLAG_RW, 596292588Sdelphij &rip_sendspace, 0, "Maximum outgoing raw IP datagram size"); 597292588SdelphijSYSCTL_ULONG(_net_inet_raw, OID_AUTO, recvspace, CTLFLAG_RW, 598292588Sdelphij &rip_recvspace, 0, "Maximum space for incoming raw IP datagrams"); 599292588Sdelphij 600292588Sdelphijstatic int 601292588Sdelphijrip_attach(struct socket *so, int proto, struct thread *td) 602292588Sdelphij{ 603292588Sdelphij struct inpcb *inp; 604292588Sdelphij int error; 605292588Sdelphij 606292588Sdelphij inp = sotoinpcb(so); 607292588Sdelphij KASSERT(inp == NULL, ("rip_attach: inp != NULL")); 608292588Sdelphij /* 609292588Sdelphij * XXXRW: Centralize privilege decision in kern_jail.c. 610292588Sdelphij */ 611292588Sdelphij if (jailed(td->td_ucred) && !jail_allow_raw_sockets) 612292588Sdelphij return (EPERM); 613292588Sdelphij error = priv_check_cred(td->td_ucred, PRIV_NETINET_RAW, 614292588Sdelphij SUSER_ALLOWJAIL); 615292588Sdelphij if (error) 616292588Sdelphij return error; 617292588Sdelphij if (proto >= IPPROTO_MAX || proto < 0) 618292588Sdelphij return EPROTONOSUPPORT; 619292588Sdelphij error = soreserve(so, rip_sendspace, rip_recvspace); 620292588Sdelphij if (error) 621292588Sdelphij return error; 622292588Sdelphij INP_INFO_WLOCK(&ripcbinfo); 623292588Sdelphij error = in_pcballoc(so, &ripcbinfo); 624292588Sdelphij if (error) { 625292588Sdelphij INP_INFO_WUNLOCK(&ripcbinfo); 626292588Sdelphij return error; 627292588Sdelphij } 628292588Sdelphij inp = (struct inpcb *)so->so_pcb; 629292588Sdelphij INP_INFO_WUNLOCK(&ripcbinfo); 630292588Sdelphij inp->inp_vflag |= INP_IPV4; 631292588Sdelphij inp->inp_ip_p = proto; 632292588Sdelphij inp->inp_ip_ttl = ip_defttl; 633292588Sdelphij INP_UNLOCK(inp); 634292588Sdelphij return 0; 635292588Sdelphij} 636292588Sdelphij 637292588Sdelphijstatic void 638292588Sdelphijrip_detach(struct socket *so) 639292588Sdelphij{ 640292588Sdelphij struct inpcb *inp; 641292588Sdelphij 642292588Sdelphij inp = sotoinpcb(so); 643292588Sdelphij KASSERT(inp != NULL, ("rip_detach: inp == NULL")); 644292588Sdelphij KASSERT(inp->inp_faddr.s_addr == INADDR_ANY, 645292588Sdelphij ("rip_detach: not closed")); 646292588Sdelphij 647292588Sdelphij INP_INFO_WLOCK(&ripcbinfo); 648292588Sdelphij INP_LOCK(inp); 649292588Sdelphij if (so == ip_mrouter && ip_mrouter_done) 650292588Sdelphij ip_mrouter_done(); 651292588Sdelphij if (ip_rsvp_force_done) 652292588Sdelphij ip_rsvp_force_done(so); 653292588Sdelphij if (so == ip_rsvpd) 654292588Sdelphij ip_rsvp_done(); 655292588Sdelphij in_pcbdetach(inp); 656292588Sdelphij in_pcbfree(inp); 657292588Sdelphij INP_INFO_WUNLOCK(&ripcbinfo); 658292588Sdelphij} 659292588Sdelphij 660292588Sdelphijstatic void 661292588Sdelphijrip_dodisconnect(struct socket *so, struct inpcb *inp) 662292588Sdelphij{ 663292588Sdelphij 664292588Sdelphij INP_LOCK_ASSERT(inp); 665292588Sdelphij 666292588Sdelphij inp->inp_faddr.s_addr = INADDR_ANY; 667292588Sdelphij SOCK_LOCK(so); 668292588Sdelphij so->so_state &= ~SS_ISCONNECTED; 669292588Sdelphij SOCK_UNLOCK(so); 670292588Sdelphij} 671292588Sdelphij 672292588Sdelphijstatic void 673292588Sdelphijrip_abort(struct socket *so) 674292588Sdelphij{ 675292588Sdelphij struct inpcb *inp; 676292588Sdelphij 677292588Sdelphij inp = sotoinpcb(so); 678292588Sdelphij KASSERT(inp != NULL, ("rip_abort: inp == NULL")); 679292588Sdelphij 680292588Sdelphij INP_INFO_WLOCK(&ripcbinfo); 681292588Sdelphij INP_LOCK(inp); 682292588Sdelphij rip_dodisconnect(so, inp); 683292588Sdelphij INP_UNLOCK(inp); 684292588Sdelphij INP_INFO_WUNLOCK(&ripcbinfo); 685292588Sdelphij} 686292588Sdelphij 687292588Sdelphijstatic void 688292588Sdelphijrip_close(struct socket *so) 689292588Sdelphij{ 690292588Sdelphij struct inpcb *inp; 691292588Sdelphij 692292588Sdelphij inp = sotoinpcb(so); 693292588Sdelphij KASSERT(inp != NULL, ("rip_close: inp == NULL")); 694292588Sdelphij 695292588Sdelphij INP_INFO_WLOCK(&ripcbinfo); 696292588Sdelphij INP_LOCK(inp); 697292588Sdelphij rip_dodisconnect(so, inp); 698292588Sdelphij INP_UNLOCK(inp); 699292588Sdelphij INP_INFO_WUNLOCK(&ripcbinfo); 700292588Sdelphij} 701292588Sdelphij 702292588Sdelphijstatic int 703292588Sdelphijrip_disconnect(struct socket *so) 704292588Sdelphij{ 705292588Sdelphij struct inpcb *inp; 706292588Sdelphij 707292588Sdelphij if ((so->so_state & SS_ISCONNECTED) == 0) 708292588Sdelphij return ENOTCONN; 709292588Sdelphij 710292588Sdelphij inp = sotoinpcb(so); 711292588Sdelphij KASSERT(inp != NULL, ("rip_disconnect: inp == NULL")); 712292588Sdelphij INP_INFO_WLOCK(&ripcbinfo); 713292588Sdelphij INP_LOCK(inp); 714292588Sdelphij rip_dodisconnect(so, inp); 715292588Sdelphij INP_UNLOCK(inp); 716292588Sdelphij INP_INFO_WUNLOCK(&ripcbinfo); 717292588Sdelphij return (0); 718292588Sdelphij} 719292588Sdelphij 720292588Sdelphijstatic int 721292588Sdelphijrip_bind(struct socket *so, struct sockaddr *nam, struct thread *td) 722292588Sdelphij{ 723292588Sdelphij struct sockaddr_in *addr = (struct sockaddr_in *)nam; 724292588Sdelphij struct inpcb *inp; 725292588Sdelphij 726292588Sdelphij if (nam->sa_len != sizeof(*addr)) 727292588Sdelphij return EINVAL; 728292588Sdelphij 729292588Sdelphij if (jailed(td->td_ucred)) { 730292588Sdelphij if (addr->sin_addr.s_addr == INADDR_ANY) 731292588Sdelphij addr->sin_addr.s_addr = 732292588Sdelphij htonl(prison_getip(td->td_ucred)); 733292588Sdelphij if (htonl(prison_getip(td->td_ucred)) != addr->sin_addr.s_addr) 734292588Sdelphij return (EADDRNOTAVAIL); 735292588Sdelphij } 736292588Sdelphij 737292588Sdelphij if (TAILQ_EMPTY(&ifnet) || 738292588Sdelphij (addr->sin_family != AF_INET && addr->sin_family != AF_IMPLINK) || 739292588Sdelphij (addr->sin_addr.s_addr && 740292588Sdelphij ifa_ifwithaddr((struct sockaddr *)addr) == 0)) 741292588Sdelphij return EADDRNOTAVAIL; 742292588Sdelphij 743292588Sdelphij inp = sotoinpcb(so); 744292588Sdelphij KASSERT(inp != NULL, ("rip_bind: inp == NULL")); 745292588Sdelphij INP_INFO_WLOCK(&ripcbinfo); 746292588Sdelphij INP_LOCK(inp); 747292588Sdelphij inp->inp_laddr = addr->sin_addr; 748292588Sdelphij INP_UNLOCK(inp); 749292588Sdelphij INP_INFO_WUNLOCK(&ripcbinfo); 750292588Sdelphij return 0; 751292588Sdelphij} 752292588Sdelphij 753292588Sdelphijstatic int 754292588Sdelphijrip_connect(struct socket *so, struct sockaddr *nam, struct thread *td) 755292588Sdelphij{ 756292588Sdelphij struct sockaddr_in *addr = (struct sockaddr_in *)nam; 757292588Sdelphij struct inpcb *inp; 758292588Sdelphij 759292588Sdelphij if (nam->sa_len != sizeof(*addr)) 760292588Sdelphij return EINVAL; 761292588Sdelphij if (TAILQ_EMPTY(&ifnet)) 762292588Sdelphij return EADDRNOTAVAIL; 763292588Sdelphij if (addr->sin_family != AF_INET && addr->sin_family != AF_IMPLINK) 764292588Sdelphij return EAFNOSUPPORT; 765292588Sdelphij 766292588Sdelphij inp = sotoinpcb(so); 767292588Sdelphij KASSERT(inp != NULL, ("rip_connect: inp == NULL")); 768292588Sdelphij INP_INFO_WLOCK(&ripcbinfo); 769292588Sdelphij INP_LOCK(inp); 770292588Sdelphij inp->inp_faddr = addr->sin_addr; 771292588Sdelphij soisconnected(so); 772292588Sdelphij INP_UNLOCK(inp); 773292588Sdelphij INP_INFO_WUNLOCK(&ripcbinfo); 774292588Sdelphij return 0; 775292588Sdelphij} 776292588Sdelphij 777292588Sdelphijstatic int 778292588Sdelphijrip_shutdown(struct socket *so) 779292588Sdelphij{ 780292588Sdelphij struct inpcb *inp; 781292588Sdelphij 782292588Sdelphij inp = sotoinpcb(so); 783292588Sdelphij KASSERT(inp != NULL, ("rip_shutdown: inp == NULL")); 784292588Sdelphij INP_LOCK(inp); 785292588Sdelphij socantsendmore(so); 786292588Sdelphij INP_UNLOCK(inp); 787292588Sdelphij return 0; 788292588Sdelphij} 789292588Sdelphij 790292588Sdelphijstatic int 791292588Sdelphijrip_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam, 792292588Sdelphij struct mbuf *control, struct thread *td) 793292588Sdelphij{ 794292588Sdelphij struct inpcb *inp; 795292588Sdelphij u_long dst; 796292588Sdelphij 797292588Sdelphij inp = sotoinpcb(so); 798292588Sdelphij KASSERT(inp != NULL, ("rip_send: inp == NULL")); 799292588Sdelphij /* 800292588Sdelphij * Note: 'dst' reads below are unlocked. 801292588Sdelphij */ 802292588Sdelphij if (so->so_state & SS_ISCONNECTED) { 803292588Sdelphij if (nam) { 804292588Sdelphij m_freem(m); 805292588Sdelphij return EISCONN; 806292588Sdelphij } 807292588Sdelphij dst = inp->inp_faddr.s_addr; /* Unlocked read. */ 808292588Sdelphij } else { 809292588Sdelphij if (nam == NULL) { 810292588Sdelphij m_freem(m); 811292588Sdelphij return ENOTCONN; 812292588Sdelphij } 813292588Sdelphij dst = ((struct sockaddr_in *)nam)->sin_addr.s_addr; 814292588Sdelphij } 815292588Sdelphij return rip_output(m, so, dst); 816292588Sdelphij} 817292588Sdelphij 818292588Sdelphijstatic int 819292588Sdelphijrip_pcblist(SYSCTL_HANDLER_ARGS) 820292588Sdelphij{ 821292588Sdelphij int error, i, n; 822292588Sdelphij struct inpcb *inp, **inp_list; 823292588Sdelphij inp_gen_t gencnt; 824292588Sdelphij struct xinpgen xig; 825292588Sdelphij 826292588Sdelphij /* 827292588Sdelphij * The process of preparing the TCB list is too time-consuming and 828292588Sdelphij * resource-intensive to repeat twice on every request. 829292588Sdelphij */ 830292588Sdelphij if (req->oldptr == 0) { 831292588Sdelphij n = ripcbinfo.ipi_count; 832292588Sdelphij req->oldidx = 2 * (sizeof xig) 833292588Sdelphij + (n + n/8) * sizeof(struct xinpcb); 834292588Sdelphij return 0; 835292588Sdelphij } 836292588Sdelphij 837292588Sdelphij if (req->newptr != 0) 838292588Sdelphij return EPERM; 839292588Sdelphij 840292588Sdelphij /* 841292588Sdelphij * OK, now we're committed to doing something. 842292588Sdelphij */ 843292588Sdelphij INP_INFO_RLOCK(&ripcbinfo); 844292588Sdelphij gencnt = ripcbinfo.ipi_gencnt; 845292588Sdelphij n = ripcbinfo.ipi_count; 846292588Sdelphij INP_INFO_RUNLOCK(&ripcbinfo); 847292588Sdelphij 848292588Sdelphij xig.xig_len = sizeof xig; 849292588Sdelphij xig.xig_count = n; 850292588Sdelphij xig.xig_gen = gencnt; 851292588Sdelphij xig.xig_sogen = so_gencnt; 852292588Sdelphij error = SYSCTL_OUT(req, &xig, sizeof xig); 853292588Sdelphij if (error) 854292588Sdelphij return error; 855292588Sdelphij 856292588Sdelphij inp_list = malloc(n * sizeof *inp_list, M_TEMP, M_WAITOK); 857292588Sdelphij if (inp_list == 0) 858292588Sdelphij return ENOMEM; 859292588Sdelphij 860292588Sdelphij INP_INFO_RLOCK(&ripcbinfo); 861292588Sdelphij for (inp = LIST_FIRST(ripcbinfo.listhead), i = 0; inp && i < n; 862292588Sdelphij inp = LIST_NEXT(inp, inp_list)) { 863292588Sdelphij INP_LOCK(inp); 864292588Sdelphij if (inp->inp_gencnt <= gencnt && 865292588Sdelphij cr_canseesocket(req->td->td_ucred, inp->inp_socket) == 0) { 866292588Sdelphij /* XXX held references? */ 867292588Sdelphij inp_list[i++] = inp; 868292588Sdelphij } 869292588Sdelphij INP_UNLOCK(inp); 870292588Sdelphij } 871292588Sdelphij INP_INFO_RUNLOCK(&ripcbinfo); 872292588Sdelphij n = i; 873292588Sdelphij 874292588Sdelphij error = 0; 875292588Sdelphij for (i = 0; i < n; i++) { 876292588Sdelphij inp = inp_list[i]; 877292588Sdelphij INP_LOCK(inp); 878292588Sdelphij if (inp->inp_gencnt <= gencnt) { 879292588Sdelphij struct xinpcb xi; 880292588Sdelphij bzero(&xi, sizeof(xi)); 881292588Sdelphij xi.xi_len = sizeof xi; 882292588Sdelphij /* XXX should avoid extra copy */ 883292588Sdelphij bcopy(inp, &xi.xi_inp, sizeof *inp); 884292588Sdelphij if (inp->inp_socket) 885292588Sdelphij sotoxsocket(inp->inp_socket, &xi.xi_socket); 886292588Sdelphij INP_UNLOCK(inp); 887292588Sdelphij error = SYSCTL_OUT(req, &xi, sizeof xi); 888292588Sdelphij } else 889292588Sdelphij INP_UNLOCK(inp); 890292588Sdelphij } 891292588Sdelphij if (!error) { 892292588Sdelphij /* 893292588Sdelphij * Give the user an updated idea of our state. 894292588Sdelphij * If the generation differs from what we told 895292588Sdelphij * her before, she knows that something happened 896292588Sdelphij * while we were processing this request, and it 897292588Sdelphij * might be necessary to retry. 898292588Sdelphij */ 899292588Sdelphij INP_INFO_RLOCK(&ripcbinfo); 900292588Sdelphij xig.xig_gen = ripcbinfo.ipi_gencnt; 901292588Sdelphij xig.xig_sogen = so_gencnt; 902292588Sdelphij xig.xig_count = ripcbinfo.ipi_count; 903292588Sdelphij INP_INFO_RUNLOCK(&ripcbinfo); 904292588Sdelphij error = SYSCTL_OUT(req, &xig, sizeof xig); 905292588Sdelphij } 906292588Sdelphij free(inp_list, M_TEMP); 907292588Sdelphij return error; 908292588Sdelphij} 909292588Sdelphij 910292588Sdelphij/* 911292588Sdelphij * This is the wrapper function for in_setsockaddr. We just pass down 912292588Sdelphij * the pcbinfo for in_setpeeraddr to lock. 913292588Sdelphij */ 914292588Sdelphijstatic int 915292588Sdelphijrip_sockaddr(struct socket *so, struct sockaddr **nam) 916292588Sdelphij{ 917292588Sdelphij return (in_setsockaddr(so, nam, &ripcbinfo)); 918292588Sdelphij} 919292588Sdelphij 920292588Sdelphij/* 921292588Sdelphij * This is the wrapper function for in_setpeeraddr. We just pass down 922292588Sdelphij * the pcbinfo for in_setpeeraddr to lock. 923292588Sdelphij */ 924292588Sdelphijstatic int 925292588Sdelphijrip_peeraddr(struct socket *so, struct sockaddr **nam) 926292588Sdelphij{ 927292588Sdelphij return (in_setpeeraddr(so, nam, &ripcbinfo)); 928292588Sdelphij} 929292588Sdelphij 930292588Sdelphij 931292588SdelphijSYSCTL_PROC(_net_inet_raw, OID_AUTO/*XXX*/, pcblist, CTLFLAG_RD, 0, 0, 932292588Sdelphij rip_pcblist, "S,xinpcb", "List of active raw IP sockets"); 933292588Sdelphij 934292588Sdelphijstruct pr_usrreqs rip_usrreqs = { 935292588Sdelphij .pru_abort = rip_abort, 936292588Sdelphij .pru_attach = rip_attach, 937292588Sdelphij .pru_bind = rip_bind, 938292588Sdelphij .pru_connect = rip_connect, 939292588Sdelphij .pru_control = in_control, 940292588Sdelphij .pru_detach = rip_detach, 941292588Sdelphij .pru_disconnect = rip_disconnect, 942292588Sdelphij .pru_peeraddr = rip_peeraddr, 943292588Sdelphij .pru_send = rip_send, 944292588Sdelphij .pru_shutdown = rip_shutdown, 945292588Sdelphij .pru_sockaddr = rip_sockaddr, 946292588Sdelphij .pru_sosetlabel = in_pcbsosetlabel, 947292588Sdelphij .pru_close = rip_close, 948292588Sdelphij}; 949292588Sdelphij