1df8bae1dSRodney W. Grimes /* 2df8bae1dSRodney W. Grimes * Copyright (c) 1982, 1986, 1988, 1993 3df8bae1dSRodney W. Grimes * The Regents of the University of California. All rights reserved. 4df8bae1dSRodney W. Grimes * 5df8bae1dSRodney W. Grimes * Redistribution and use in source and binary forms, with or without 6df8bae1dSRodney W. Grimes * modification, are permitted provided that the following conditions 7df8bae1dSRodney W. Grimes * are met: 8df8bae1dSRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 9df8bae1dSRodney W. Grimes * notice, this list of conditions and the following disclaimer. 10df8bae1dSRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 11df8bae1dSRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 12df8bae1dSRodney W. Grimes * documentation and/or other materials provided with the distribution. 13df8bae1dSRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 14df8bae1dSRodney W. Grimes * must display the following acknowledgement: 15df8bae1dSRodney W. Grimes * This product includes software developed by the University of 16df8bae1dSRodney W. Grimes * California, Berkeley and its contributors. 17df8bae1dSRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 18df8bae1dSRodney W. Grimes * may be used to endorse or promote products derived from this software 19df8bae1dSRodney W. Grimes * without specific prior written permission. 20df8bae1dSRodney W. Grimes * 21df8bae1dSRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22df8bae1dSRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23df8bae1dSRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24df8bae1dSRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25df8bae1dSRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26df8bae1dSRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27df8bae1dSRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28df8bae1dSRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29df8bae1dSRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30df8bae1dSRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31df8bae1dSRodney W. Grimes * SUCH DAMAGE. 32df8bae1dSRodney W. Grimes * 33df8bae1dSRodney W. Grimes * @(#)raw_ip.c 8.2 (Berkeley) 1/4/94 34838ecf42SGarrett Wollman * $Id: raw_ip.c,v 1.13 1995/01/26 18:59:02 wollman Exp $ 35df8bae1dSRodney W. Grimes */ 36df8bae1dSRodney W. Grimes 37df8bae1dSRodney W. Grimes #include <sys/param.h> 38df8bae1dSRodney W. Grimes #include <sys/malloc.h> 39df8bae1dSRodney W. Grimes #include <sys/mbuf.h> 40df8bae1dSRodney W. Grimes #include <sys/socket.h> 41df8bae1dSRodney W. Grimes #include <sys/protosw.h> 42df8bae1dSRodney W. Grimes #include <sys/socketvar.h> 43df8bae1dSRodney W. Grimes #include <sys/errno.h> 44df8bae1dSRodney W. Grimes #include <sys/systm.h> 45df8bae1dSRodney W. Grimes 46df8bae1dSRodney W. Grimes #include <net/if.h> 47df8bae1dSRodney W. Grimes #include <net/route.h> 48df8bae1dSRodney W. Grimes 49df8bae1dSRodney W. Grimes #include <netinet/in.h> 50df8bae1dSRodney W. Grimes #include <netinet/in_systm.h> 51df8bae1dSRodney W. Grimes #include <netinet/ip.h> 52df8bae1dSRodney W. Grimes #include <netinet/ip_var.h> 53df8bae1dSRodney W. Grimes #include <netinet/ip_mroute.h> 54df8bae1dSRodney W. Grimes #include <netinet/in_pcb.h> 55df8bae1dSRodney W. Grimes 56100ba1a6SJordan K. Hubbard #include <netinet/ip_fw.h> 57100ba1a6SJordan K. Hubbard 58df8bae1dSRodney W. Grimes struct inpcb rawinpcb; 59df8bae1dSRodney W. Grimes 60df8bae1dSRodney W. Grimes /* 61df8bae1dSRodney W. Grimes * Nominal space allocated to a raw ip socket. 62df8bae1dSRodney W. Grimes */ 63df8bae1dSRodney W. Grimes #define RIPSNDQ 8192 64df8bae1dSRodney W. Grimes #define RIPRCVQ 8192 65df8bae1dSRodney W. Grimes 66df8bae1dSRodney W. Grimes /* 67df8bae1dSRodney W. Grimes * Raw interface to IP protocol. 68df8bae1dSRodney W. Grimes */ 69df8bae1dSRodney W. Grimes 70df8bae1dSRodney W. Grimes /* 71df8bae1dSRodney W. Grimes * Initialize raw connection block q. 72df8bae1dSRodney W. Grimes */ 73df8bae1dSRodney W. Grimes void 74df8bae1dSRodney W. Grimes rip_init() 75df8bae1dSRodney W. Grimes { 76df8bae1dSRodney W. Grimes 77df8bae1dSRodney W. Grimes rawinpcb.inp_next = rawinpcb.inp_prev = &rawinpcb; 78df8bae1dSRodney W. Grimes } 79df8bae1dSRodney W. Grimes 80df8bae1dSRodney W. Grimes struct sockaddr_in ripsrc = { sizeof(ripsrc), AF_INET }; 81df8bae1dSRodney W. Grimes /* 82df8bae1dSRodney W. Grimes * Setup generic address and protocol structures 83df8bae1dSRodney W. Grimes * for raw_input routine, then pass them along with 84df8bae1dSRodney W. Grimes * mbuf chain. 85df8bae1dSRodney W. Grimes */ 86df8bae1dSRodney W. Grimes void 87df8bae1dSRodney W. Grimes rip_input(m) 88df8bae1dSRodney W. Grimes struct mbuf *m; 89df8bae1dSRodney W. Grimes { 90df8bae1dSRodney W. Grimes register struct ip *ip = mtod(m, struct ip *); 91df8bae1dSRodney W. Grimes register struct inpcb *inp; 92df8bae1dSRodney W. Grimes struct socket *last = 0; 93df8bae1dSRodney W. Grimes 94df8bae1dSRodney W. Grimes ripsrc.sin_addr = ip->ip_src; 95df8bae1dSRodney W. Grimes for (inp = rawinpcb.inp_next; inp != &rawinpcb; inp = inp->inp_next) { 96df8bae1dSRodney W. Grimes if (inp->inp_ip.ip_p && inp->inp_ip.ip_p != ip->ip_p) 97df8bae1dSRodney W. Grimes continue; 98df8bae1dSRodney W. Grimes if (inp->inp_laddr.s_addr && 99df8bae1dSRodney W. Grimes inp->inp_laddr.s_addr == ip->ip_dst.s_addr) 100df8bae1dSRodney W. Grimes continue; 101df8bae1dSRodney W. Grimes if (inp->inp_faddr.s_addr && 102df8bae1dSRodney W. Grimes inp->inp_faddr.s_addr == ip->ip_src.s_addr) 103df8bae1dSRodney W. Grimes continue; 104df8bae1dSRodney W. Grimes if (last) { 105623ae52eSPoul-Henning Kamp struct mbuf *n = m_copy(m, 0, (int)M_COPYALL); 106623ae52eSPoul-Henning Kamp if (n) { 107623ae52eSPoul-Henning Kamp if (sbappendaddr(&last->so_rcv, 108623ae52eSPoul-Henning Kamp (struct sockaddr *)&ripsrc, n, 109623ae52eSPoul-Henning Kamp (struct mbuf *)0) == 0) 110df8bae1dSRodney W. Grimes /* should notify about lost packet */ 111df8bae1dSRodney W. Grimes m_freem(n); 112df8bae1dSRodney W. Grimes else 113df8bae1dSRodney W. Grimes sorwakeup(last); 114df8bae1dSRodney W. Grimes } 115df8bae1dSRodney W. Grimes } 116df8bae1dSRodney W. Grimes last = inp->inp_socket; 117df8bae1dSRodney W. Grimes } 118df8bae1dSRodney W. Grimes if (last) { 119623ae52eSPoul-Henning Kamp if (sbappendaddr(&last->so_rcv, (struct sockaddr *)&ripsrc, 120df8bae1dSRodney W. Grimes m, (struct mbuf *)0) == 0) 121df8bae1dSRodney W. Grimes m_freem(m); 122df8bae1dSRodney W. Grimes else 123df8bae1dSRodney W. Grimes sorwakeup(last); 124df8bae1dSRodney W. Grimes } else { 125df8bae1dSRodney W. Grimes m_freem(m); 126df8bae1dSRodney W. Grimes ipstat.ips_noproto++; 127df8bae1dSRodney W. Grimes ipstat.ips_delivered--; 128df8bae1dSRodney W. Grimes } 129df8bae1dSRodney W. Grimes } 130df8bae1dSRodney W. Grimes 131df8bae1dSRodney W. Grimes /* 132df8bae1dSRodney W. Grimes * Generate IP header and pass packet to ip_output. 133df8bae1dSRodney W. Grimes * Tack on options user may have setup with control call. 134df8bae1dSRodney W. Grimes */ 135df8bae1dSRodney W. Grimes int 136df8bae1dSRodney W. Grimes rip_output(m, so, dst) 137df8bae1dSRodney W. Grimes register struct mbuf *m; 138df8bae1dSRodney W. Grimes struct socket *so; 139df8bae1dSRodney W. Grimes u_long dst; 140df8bae1dSRodney W. Grimes { 141df8bae1dSRodney W. Grimes register struct ip *ip; 142df8bae1dSRodney W. Grimes register struct inpcb *inp = sotoinpcb(so); 143df8bae1dSRodney W. Grimes struct mbuf *opts; 144df8bae1dSRodney W. Grimes int flags = (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST; 145df8bae1dSRodney W. Grimes 146df8bae1dSRodney W. Grimes /* 147df8bae1dSRodney W. Grimes * If the user handed us a complete IP packet, use it. 148df8bae1dSRodney W. Grimes * Otherwise, allocate an mbuf for a header and fill it in. 149df8bae1dSRodney W. Grimes */ 150df8bae1dSRodney W. Grimes if ((inp->inp_flags & INP_HDRINCL) == 0) { 151df8bae1dSRodney W. Grimes M_PREPEND(m, sizeof(struct ip), M_WAIT); 152df8bae1dSRodney W. Grimes ip = mtod(m, struct ip *); 153df8bae1dSRodney W. Grimes ip->ip_tos = 0; 154df8bae1dSRodney W. Grimes ip->ip_off = 0; 155df8bae1dSRodney W. Grimes ip->ip_p = inp->inp_ip.ip_p; 156df8bae1dSRodney W. Grimes ip->ip_len = m->m_pkthdr.len; 157df8bae1dSRodney W. Grimes ip->ip_src = inp->inp_laddr; 158df8bae1dSRodney W. Grimes ip->ip_dst.s_addr = dst; 159df8bae1dSRodney W. Grimes ip->ip_ttl = MAXTTL; 160df8bae1dSRodney W. Grimes opts = inp->inp_options; 161df8bae1dSRodney W. Grimes } else { 162df8bae1dSRodney W. Grimes ip = mtod(m, struct ip *); 163df8bae1dSRodney W. Grimes if (ip->ip_id == 0) 164df8bae1dSRodney W. Grimes ip->ip_id = htons(ip_id++); 165df8bae1dSRodney W. Grimes opts = NULL; 166df8bae1dSRodney W. Grimes /* XXX prevent ip_output from overwriting header fields */ 167df8bae1dSRodney W. Grimes flags |= IP_RAWOUTPUT; 168df8bae1dSRodney W. Grimes ipstat.ips_rawout++; 169df8bae1dSRodney W. Grimes } 170df8bae1dSRodney W. Grimes return (ip_output(m, opts, &inp->inp_route, flags, inp->inp_moptions)); 171df8bae1dSRodney W. Grimes } 172df8bae1dSRodney W. Grimes 173df8bae1dSRodney W. Grimes /* 174df8bae1dSRodney W. Grimes * Raw IP socket option processing. 175df8bae1dSRodney W. Grimes */ 176df8bae1dSRodney W. Grimes int 177df8bae1dSRodney W. Grimes rip_ctloutput(op, so, level, optname, m) 178df8bae1dSRodney W. Grimes int op; 179df8bae1dSRodney W. Grimes struct socket *so; 180df8bae1dSRodney W. Grimes int level, optname; 181df8bae1dSRodney W. Grimes struct mbuf **m; 182df8bae1dSRodney W. Grimes { 183df8bae1dSRodney W. Grimes register struct inpcb *inp = sotoinpcb(so); 184df8bae1dSRodney W. Grimes register int error; 185df8bae1dSRodney W. Grimes 186aedcdea1SDavid Greenman if (level != IPPROTO_IP) { 187aedcdea1SDavid Greenman if (op == PRCO_SETOPT && *m) 188aedcdea1SDavid Greenman (void)m_free(*m); 189df8bae1dSRodney W. Grimes return (EINVAL); 190aedcdea1SDavid Greenman } 191df8bae1dSRodney W. Grimes 192df8bae1dSRodney W. Grimes switch (optname) { 193df8bae1dSRodney W. Grimes 194df8bae1dSRodney W. Grimes case IP_HDRINCL: 195df8bae1dSRodney W. Grimes if (op == PRCO_SETOPT || op == PRCO_GETOPT) { 196df8bae1dSRodney W. Grimes if (m == 0 || *m == 0 || (*m)->m_len < sizeof (int)) 197df8bae1dSRodney W. Grimes return (EINVAL); 198df8bae1dSRodney W. Grimes if (op == PRCO_SETOPT) { 199df8bae1dSRodney W. Grimes if (*mtod(*m, int *)) 200df8bae1dSRodney W. Grimes inp->inp_flags |= INP_HDRINCL; 201df8bae1dSRodney W. Grimes else 202df8bae1dSRodney W. Grimes inp->inp_flags &= ~INP_HDRINCL; 203df8bae1dSRodney W. Grimes (void)m_free(*m); 204df8bae1dSRodney W. Grimes } else { 205df8bae1dSRodney W. Grimes (*m)->m_len = sizeof (int); 206df8bae1dSRodney W. Grimes *mtod(*m, int *) = inp->inp_flags & INP_HDRINCL; 207df8bae1dSRodney W. Grimes } 208df8bae1dSRodney W. Grimes return (0); 209df8bae1dSRodney W. Grimes } 210df8bae1dSRodney W. Grimes break; 211df8bae1dSRodney W. Grimes 2124dd1662bSUgen J.S. Antsilevich case IP_FW_ADD: 2134dd1662bSUgen J.S. Antsilevich case IP_FW_DEL: 214100ba1a6SJordan K. Hubbard case IP_FW_FLUSH: 215100ba1a6SJordan K. Hubbard case IP_FW_POLICY: 2164dd1662bSUgen J.S. Antsilevich if (ip_fw_ctl_ptr==NULL) { 2174dd1662bSUgen J.S. Antsilevich if (*m) 2184dd1662bSUgen J.S. Antsilevich (void)m_free(*m); 2194dd1662bSUgen J.S. Antsilevich return(EINVAL); 2204dd1662bSUgen J.S. Antsilevich } 221100ba1a6SJordan K. Hubbard 222ad63b513SJordan K. Hubbard if (op == PRCO_SETOPT) { 2234dd1662bSUgen J.S. Antsilevich error=(*ip_fw_ctl_ptr)(optname, *m); 224ad63b513SJordan K. Hubbard if (*m) 225ad63b513SJordan K. Hubbard (void)m_free(*m); 226ad63b513SJordan K. Hubbard } 227100ba1a6SJordan K. Hubbard else 228100ba1a6SJordan K. Hubbard error=EINVAL; 229100ba1a6SJordan K. Hubbard return(error); 2304dd1662bSUgen J.S. Antsilevich 23163f8d699SJordan K. Hubbard case IP_ACCT_DEL: 23263f8d699SJordan K. Hubbard case IP_ACCT_ADD: 2333107b31bSUgen J.S. Antsilevich case IP_ACCT_CLR: 23463f8d699SJordan K. Hubbard case IP_ACCT_FLUSH: 23563f8d699SJordan K. Hubbard case IP_ACCT_ZERO: 2364dd1662bSUgen J.S. Antsilevich if (ip_acct_ctl_ptr==NULL) { 2374dd1662bSUgen J.S. Antsilevich if (*m) 2384dd1662bSUgen J.S. Antsilevich (void)m_free(*m); 2394dd1662bSUgen J.S. Antsilevich return(EINVAL); 2404dd1662bSUgen J.S. Antsilevich } 241100ba1a6SJordan K. Hubbard 24263f8d699SJordan K. Hubbard if (op = PRCO_SETOPT) { 2434dd1662bSUgen J.S. Antsilevich error=(*ip_acct_ctl_ptr)(optname, *m); 24463f8d699SJordan K. Hubbard if (*m) 24563f8d699SJordan K. Hubbard (void)m_free(*m); 24663f8d699SJordan K. Hubbard } 24763f8d699SJordan K. Hubbard else 24863f8d699SJordan K. Hubbard error=EINVAL; 24963f8d699SJordan K. Hubbard return(error); 250100ba1a6SJordan K. Hubbard 251f0068c4aSGarrett Wollman case IP_RSVP_ON: 252479bb8daSGarrett Wollman return ip_rsvp_init(so); 253f0068c4aSGarrett Wollman break; 254f0068c4aSGarrett Wollman 255f0068c4aSGarrett Wollman case IP_RSVP_OFF: 256479bb8daSGarrett Wollman return ip_rsvp_done(); 257f0068c4aSGarrett Wollman break; 258f0068c4aSGarrett Wollman 259df8bae1dSRodney W. Grimes case DVMRP_INIT: 260df8bae1dSRodney W. Grimes case DVMRP_DONE: 261df8bae1dSRodney W. Grimes case DVMRP_ADD_VIF: 262df8bae1dSRodney W. Grimes case DVMRP_DEL_VIF: 263f0068c4aSGarrett Wollman case DVMRP_ADD_MFC: 264f0068c4aSGarrett Wollman case DVMRP_DEL_MFC: 265df8bae1dSRodney W. Grimes if (op == PRCO_SETOPT) { 266df8bae1dSRodney W. Grimes error = ip_mrouter_cmd(optname, so, *m); 267df8bae1dSRodney W. Grimes if (*m) 268df8bae1dSRodney W. Grimes (void)m_free(*m); 269df8bae1dSRodney W. Grimes } else 270df8bae1dSRodney W. Grimes error = EINVAL; 271df8bae1dSRodney W. Grimes return (error); 272df8bae1dSRodney W. Grimes } 273df8bae1dSRodney W. Grimes return (ip_ctloutput(op, so, level, optname, m)); 274df8bae1dSRodney W. Grimes } 275df8bae1dSRodney W. Grimes 276df8bae1dSRodney W. Grimes u_long rip_sendspace = RIPSNDQ; 277df8bae1dSRodney W. Grimes u_long rip_recvspace = RIPRCVQ; 278df8bae1dSRodney W. Grimes 279df8bae1dSRodney W. Grimes /*ARGSUSED*/ 280df8bae1dSRodney W. Grimes int 281df8bae1dSRodney W. Grimes rip_usrreq(so, req, m, nam, control) 282df8bae1dSRodney W. Grimes register struct socket *so; 283df8bae1dSRodney W. Grimes int req; 284df8bae1dSRodney W. Grimes struct mbuf *m, *nam, *control; 285df8bae1dSRodney W. Grimes { 286df8bae1dSRodney W. Grimes register int error = 0; 287df8bae1dSRodney W. Grimes register struct inpcb *inp = sotoinpcb(so); 288df8bae1dSRodney W. Grimes switch (req) { 289df8bae1dSRodney W. Grimes 290df8bae1dSRodney W. Grimes case PRU_ATTACH: 291df8bae1dSRodney W. Grimes if (inp) 292df8bae1dSRodney W. Grimes panic("rip_attach"); 293df8bae1dSRodney W. Grimes if ((so->so_state & SS_PRIV) == 0) { 294df8bae1dSRodney W. Grimes error = EACCES; 295df8bae1dSRodney W. Grimes break; 296df8bae1dSRodney W. Grimes } 297df8bae1dSRodney W. Grimes if ((error = soreserve(so, rip_sendspace, rip_recvspace)) || 298df8bae1dSRodney W. Grimes (error = in_pcballoc(so, &rawinpcb))) 299df8bae1dSRodney W. Grimes break; 300df8bae1dSRodney W. Grimes inp = (struct inpcb *)so->so_pcb; 301df8bae1dSRodney W. Grimes inp->inp_ip.ip_p = (int)nam; 302df8bae1dSRodney W. Grimes break; 303df8bae1dSRodney W. Grimes 304df8bae1dSRodney W. Grimes case PRU_DISCONNECT: 305df8bae1dSRodney W. Grimes if ((so->so_state & SS_ISCONNECTED) == 0) { 306df8bae1dSRodney W. Grimes error = ENOTCONN; 307df8bae1dSRodney W. Grimes break; 308df8bae1dSRodney W. Grimes } 309df8bae1dSRodney W. Grimes /* FALLTHROUGH */ 310df8bae1dSRodney W. Grimes case PRU_ABORT: 311df8bae1dSRodney W. Grimes soisdisconnected(so); 312df8bae1dSRodney W. Grimes /* FALLTHROUGH */ 313df8bae1dSRodney W. Grimes case PRU_DETACH: 314df8bae1dSRodney W. Grimes if (inp == 0) 315df8bae1dSRodney W. Grimes panic("rip_detach"); 316df8bae1dSRodney W. Grimes if (so == ip_mrouter) 317df8bae1dSRodney W. Grimes ip_mrouter_done(); 318838ecf42SGarrett Wollman if (so == ip_rsvpd) 319838ecf42SGarrett Wollman ip_rsvp_done(); 320df8bae1dSRodney W. Grimes in_pcbdetach(inp); 321df8bae1dSRodney W. Grimes break; 322df8bae1dSRodney W. Grimes 323df8bae1dSRodney W. Grimes case PRU_BIND: 324df8bae1dSRodney W. Grimes { 325df8bae1dSRodney W. Grimes struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *); 326df8bae1dSRodney W. Grimes 327df8bae1dSRodney W. Grimes if (nam->m_len != sizeof(*addr)) { 328df8bae1dSRodney W. Grimes error = EINVAL; 329df8bae1dSRodney W. Grimes break; 330df8bae1dSRodney W. Grimes } 331df8bae1dSRodney W. Grimes if ((ifnet == 0) || 332df8bae1dSRodney W. Grimes ((addr->sin_family != AF_INET) && 333df8bae1dSRodney W. Grimes (addr->sin_family != AF_IMPLINK)) || 334df8bae1dSRodney W. Grimes (addr->sin_addr.s_addr && 335df8bae1dSRodney W. Grimes ifa_ifwithaddr((struct sockaddr *)addr) == 0)) { 336df8bae1dSRodney W. Grimes error = EADDRNOTAVAIL; 337df8bae1dSRodney W. Grimes break; 338df8bae1dSRodney W. Grimes } 339df8bae1dSRodney W. Grimes inp->inp_laddr = addr->sin_addr; 340df8bae1dSRodney W. Grimes break; 341df8bae1dSRodney W. Grimes } 342df8bae1dSRodney W. Grimes case PRU_CONNECT: 343df8bae1dSRodney W. Grimes { 344df8bae1dSRodney W. Grimes struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *); 345df8bae1dSRodney W. Grimes 346df8bae1dSRodney W. Grimes if (nam->m_len != sizeof(*addr)) { 347df8bae1dSRodney W. Grimes error = EINVAL; 348df8bae1dSRodney W. Grimes break; 349df8bae1dSRodney W. Grimes } 350df8bae1dSRodney W. Grimes if (ifnet == 0) { 351df8bae1dSRodney W. Grimes error = EADDRNOTAVAIL; 352df8bae1dSRodney W. Grimes break; 353df8bae1dSRodney W. Grimes } 354df8bae1dSRodney W. Grimes if ((addr->sin_family != AF_INET) && 355df8bae1dSRodney W. Grimes (addr->sin_family != AF_IMPLINK)) { 356df8bae1dSRodney W. Grimes error = EAFNOSUPPORT; 357df8bae1dSRodney W. Grimes break; 358df8bae1dSRodney W. Grimes } 359df8bae1dSRodney W. Grimes inp->inp_faddr = addr->sin_addr; 360df8bae1dSRodney W. Grimes soisconnected(so); 361df8bae1dSRodney W. Grimes break; 362df8bae1dSRodney W. Grimes } 363df8bae1dSRodney W. Grimes 364df8bae1dSRodney W. Grimes case PRU_CONNECT2: 365df8bae1dSRodney W. Grimes error = EOPNOTSUPP; 366df8bae1dSRodney W. Grimes break; 367df8bae1dSRodney W. Grimes 368df8bae1dSRodney W. Grimes /* 369df8bae1dSRodney W. Grimes * Mark the connection as being incapable of further input. 370df8bae1dSRodney W. Grimes */ 371df8bae1dSRodney W. Grimes case PRU_SHUTDOWN: 372df8bae1dSRodney W. Grimes socantsendmore(so); 373df8bae1dSRodney W. Grimes break; 374df8bae1dSRodney W. Grimes 375df8bae1dSRodney W. Grimes /* 376df8bae1dSRodney W. Grimes * Ship a packet out. The appropriate raw output 377df8bae1dSRodney W. Grimes * routine handles any massaging necessary. 378df8bae1dSRodney W. Grimes */ 379df8bae1dSRodney W. Grimes case PRU_SEND: 380df8bae1dSRodney W. Grimes { 381df8bae1dSRodney W. Grimes register u_long dst; 382df8bae1dSRodney W. Grimes 383df8bae1dSRodney W. Grimes if (so->so_state & SS_ISCONNECTED) { 384df8bae1dSRodney W. Grimes if (nam) { 385df8bae1dSRodney W. Grimes error = EISCONN; 386df8bae1dSRodney W. Grimes break; 387df8bae1dSRodney W. Grimes } 388df8bae1dSRodney W. Grimes dst = inp->inp_faddr.s_addr; 389df8bae1dSRodney W. Grimes } else { 390df8bae1dSRodney W. Grimes if (nam == NULL) { 391df8bae1dSRodney W. Grimes error = ENOTCONN; 392df8bae1dSRodney W. Grimes break; 393df8bae1dSRodney W. Grimes } 394df8bae1dSRodney W. Grimes dst = mtod(nam, struct sockaddr_in *)->sin_addr.s_addr; 395df8bae1dSRodney W. Grimes } 396df8bae1dSRodney W. Grimes error = rip_output(m, so, dst); 397df8bae1dSRodney W. Grimes m = NULL; 398df8bae1dSRodney W. Grimes break; 399df8bae1dSRodney W. Grimes } 400df8bae1dSRodney W. Grimes 401df8bae1dSRodney W. Grimes case PRU_SENSE: 402df8bae1dSRodney W. Grimes /* 403df8bae1dSRodney W. Grimes * stat: don't bother with a blocksize. 404df8bae1dSRodney W. Grimes */ 405df8bae1dSRodney W. Grimes return (0); 406df8bae1dSRodney W. Grimes 407df8bae1dSRodney W. Grimes /* 408df8bae1dSRodney W. Grimes * Not supported. 409df8bae1dSRodney W. Grimes */ 410df8bae1dSRodney W. Grimes case PRU_RCVOOB: 411df8bae1dSRodney W. Grimes case PRU_RCVD: 412df8bae1dSRodney W. Grimes case PRU_LISTEN: 413df8bae1dSRodney W. Grimes case PRU_ACCEPT: 414df8bae1dSRodney W. Grimes case PRU_SENDOOB: 415df8bae1dSRodney W. Grimes error = EOPNOTSUPP; 416df8bae1dSRodney W. Grimes break; 417df8bae1dSRodney W. Grimes 418df8bae1dSRodney W. Grimes case PRU_SOCKADDR: 419df8bae1dSRodney W. Grimes in_setsockaddr(inp, nam); 420df8bae1dSRodney W. Grimes break; 421df8bae1dSRodney W. Grimes 422df8bae1dSRodney W. Grimes case PRU_PEERADDR: 423df8bae1dSRodney W. Grimes in_setpeeraddr(inp, nam); 424df8bae1dSRodney W. Grimes break; 425df8bae1dSRodney W. Grimes 426df8bae1dSRodney W. Grimes default: 427df8bae1dSRodney W. Grimes panic("rip_usrreq"); 428df8bae1dSRodney W. Grimes } 429df8bae1dSRodney W. Grimes if (m != NULL) 430df8bae1dSRodney W. Grimes m_freem(m); 431df8bae1dSRodney W. Grimes return (error); 432df8bae1dSRodney W. Grimes } 433