raw_usrreq.c revision 25201
1207618Srdivacky/* 2198090Srdivacky * Copyright (c) 1980, 1986, 1993 3353358Sdim * The Regents of the University of California. All rights reserved. 4353358Sdim * 5353358Sdim * Redistribution and use in source and binary forms, with or without 6198090Srdivacky * modification, are permitted provided that the following conditions 7198090Srdivacky * are met: 8198090Srdivacky * 1. Redistributions of source code must retain the above copyright 9198090Srdivacky * notice, this list of conditions and the following disclaimer. 10198090Srdivacky * 2. Redistributions in binary form must reproduce the above copyright 11198090Srdivacky * notice, this list of conditions and the following disclaimer in the 12198090Srdivacky * documentation and/or other materials provided with the distribution. 13198090Srdivacky * 3. All advertising materials mentioning features or use of this software 14198090Srdivacky * must display the following acknowledgement: 15198090Srdivacky * This product includes software developed by the University of 16321369Sdim * California, Berkeley and its contributors. 17249423Sdim * 4. Neither the name of the University nor the names of its contributors 18327952Sdim * may be used to endorse or promote products derived from this software 19198090Srdivacky * without specific prior written permission. 20198090Srdivacky * 21198090Srdivacky * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22198090Srdivacky * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23280031Sdim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24321369Sdim * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25353358Sdim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26249423Sdim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27249423Sdim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28309124Sdim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29296417Sdim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30198090Srdivacky * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31249423Sdim * SUCH DAMAGE. 32314564Sdim * 33314564Sdim * @(#)raw_usrreq.c 8.1 (Berkeley) 6/10/93 34314564Sdim * $Id: raw_usrreq.c,v 1.11 1997/04/14 18:23:25 phk Exp $ 35314564Sdim */ 36314564Sdim 37314564Sdim#include <sys/param.h> 38314564Sdim#include <sys/queue.h> 39314564Sdim#include <sys/systm.h> 40314564Sdim#include <sys/mbuf.h> 41314564Sdim#include <sys/domain.h> 42314564Sdim#include <sys/proc.h> 43314564Sdim#include <sys/protosw.h> 44314564Sdim#include <sys/socket.h> 45314564Sdim#include <sys/socketvar.h> 46314564Sdim#include <sys/errno.h> 47314564Sdim 48314564Sdim#include <net/if.h> 49314564Sdim#include <net/route.h> 50314564Sdim#include <net/netisr.h> 51249423Sdim#include <net/raw_cb.h> 52198090Srdivacky 53341825Sdim/* 54249423Sdim * Initialize raw connection block q. 55249423Sdim */ 56249423Sdimvoid 57249423Sdimraw_init() 58249423Sdim{ 59249423Sdim LIST_INIT(&rawcb_list); 60249423Sdim} 61249423Sdim 62249423Sdim 63249423Sdim/* 64249423Sdim * Raw protocol input routine. Find the socket 65249423Sdim * associated with the packet(s) and move them over. If 66249423Sdim * nothing exists for this packet, drop it. 67249423Sdim */ 68249423Sdim/* 69341825Sdim * Raw protocol interface. 70353358Sdim */ 71249423Sdimvoid 72341825Sdimraw_input(m0, proto, src, dst) 73353358Sdim struct mbuf *m0; 74249423Sdim register struct sockproto *proto; 75344779Sdim struct sockaddr *src, *dst; 76344779Sdim{ 77344779Sdim register struct rawcb *rp; 78249423Sdim register struct mbuf *m = m0; 79344779Sdim register int sockets = 0; 80344779Sdim struct socket *last; 81344779Sdim 82344779Sdim last = 0; 83344779Sdim LIST_FOREACH(rp, &rawcb_list, list) { 84249423Sdim if (rp->rcb_proto.sp_family != proto->sp_family) 85249423Sdim continue; 86249423Sdim if (rp->rcb_proto.sp_protocol && 87249423Sdim rp->rcb_proto.sp_protocol != proto->sp_protocol) 88249423Sdim continue; 89249423Sdim /* 90198090Srdivacky * We assume the lower level routines have 91344779Sdim * placed the address in a canonical format 92344779Sdim * suitable for a structure comparison. 93249423Sdim * 94344779Sdim * Note that if the lengths are not the same 95344779Sdim * the comparison will fail at the first byte. 96249423Sdim */ 97198090Srdivacky#define equal(a1, a2) \ 98341825Sdim (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0) 99288943Sdim if (rp->rcb_laddr && !equal(rp->rcb_laddr, dst)) 100249423Sdim continue; 101249423Sdim if (rp->rcb_faddr && !equal(rp->rcb_faddr, src)) 102198090Srdivacky continue; 103249423Sdim if (last) { 104249423Sdim struct mbuf *n; 105249423Sdim n = m_copy(m, 0, (int)M_COPYALL); 106198090Srdivacky if (n) { 107341825Sdim if (sbappendaddr(&last->so_rcv, src, 108249423Sdim n, (struct mbuf *)0) == 0) 109249423Sdim /* should notify about lost packet */ 110249423Sdim m_freem(n); 111249423Sdim else { 112249423Sdim sorwakeup(last); 113198090Srdivacky sockets++; 114341825Sdim } 115327952Sdim } 116327952Sdim } 117327952Sdim last = rp->rcb_socket; 118327952Sdim } 119327952Sdim if (last) { 120344779Sdim if (sbappendaddr(&last->so_rcv, src, 121344779Sdim m, (struct mbuf *)0) == 0) 122344779Sdim m_freem(m); 123344779Sdim else { 124344779Sdim sorwakeup(last); 125344779Sdim sockets++; 126344779Sdim } 127341825Sdim } else 128249423Sdim m_freem(m); 129249423Sdim} 130249423Sdim 131249423Sdim/*ARGSUSED*/ 132234353Sdimvoid 133344779Sdimraw_ctlinput(cmd, arg, dummy) 134344779Sdim int cmd; 135344779Sdim struct sockaddr *arg; 136344779Sdim void *dummy; 137344779Sdim{ 138344779Sdim 139344779Sdim if (cmd < 0 || cmd > PRC_NCMDS) 140344779Sdim return; 141344779Sdim /* INCOMPLETE */ 142344779Sdim} 143344779Sdim 144314564Sdimstatic int 145314564Sdimraw_uabort(struct socket *so) 146314564Sdim{ 147314564Sdim struct rawcb *rp = sotorawcb(so); 148314564Sdim 149314564Sdim if (rp == 0) 150314564Sdim return EINVAL; 151314564Sdim raw_disconnect(rp); 152314564Sdim sofree(so); 153314564Sdim soisdisconnected(so); 154314564Sdim return 0; 155314564Sdim} 156314564Sdim 157314564Sdim/* pru_accept is EOPNOTSUPP */ 158314564Sdim 159314564Sdimstatic int 160314564Sdimraw_uattach(struct socket *so, int proto, struct proc *p) 161314564Sdim{ 162314564Sdim struct rawcb *rp = sotorawcb(so); 163314564Sdim int error; 164314564Sdim 165314564Sdim if (rp == 0) 166314564Sdim return EINVAL; 167314564Sdim if (p && (error = suser(p->p_ucred, &p->p_acflag)) != 0) 168314564Sdim return error; 169314564Sdim return raw_attach(so, proto); 170314564Sdim} 171321369Sdim 172327952Sdimstatic int 173327952Sdimraw_ubind(struct socket *so, struct mbuf *nam, struct proc *p) 174327952Sdim{ 175327952Sdim return EINVAL; 176321369Sdim} 177321369Sdim 178327952Sdimstatic int 179327952Sdimraw_uconnect(struct socket *so, struct mbuf *nam, struct proc *p) 180327952Sdim{ 181314564Sdim return EINVAL; 182314564Sdim} 183314564Sdim 184314564Sdim/* pru_connect2 is EOPNOTSUPP */ 185314564Sdim/* pru_control is EOPNOTSUPP */ 186314564Sdim 187314564Sdimstatic int 188314564Sdimraw_udetach(struct socket *so) 189314564Sdim{ 190314564Sdim struct rawcb *rp = sotorawcb(so); 191314564Sdim 192314564Sdim if (rp == 0) 193314564Sdim return EINVAL; 194314564Sdim 195314564Sdim raw_detach(rp); 196341825Sdim return 0; 197314564Sdim} 198314564Sdim 199314564Sdimstatic int 200321369Sdimraw_udisconnect(struct socket *so) 201321369Sdim{ 202353358Sdim struct rawcb *rp = sotorawcb(so); 203321369Sdim 204341825Sdim if (rp == 0) 205296417Sdim return EINVAL; 206296417Sdim if (rp->rcb_faddr == 0) { 207309124Sdim return ENOTCONN; 208309124Sdim } 209309124Sdim raw_disconnect(rp); 210309124Sdim soisdisconnected(so); 211296417Sdim return 0; 212296417Sdim} 213296417Sdim 214296417Sdim/* pru_listen is EOPNOTSUPP */ 215327952Sdim 216353358Sdimstatic int 217327952Sdimraw_upeeraddr(struct socket *so, struct mbuf *nam) 218327952Sdim{ 219327952Sdim struct rawcb *rp = sotorawcb(so); 220198090Srdivacky unsigned len; 221341825Sdim 222296417Sdim if (rp == 0) 223296417Sdim return EINVAL; 224296417Sdim if (rp->rcb_faddr == 0) { 225296417Sdim return ENOTCONN; 226314564Sdim } 227353358Sdim len = rp->rcb_faddr->sa_len; 228314564Sdim bcopy((caddr_t)rp->rcb_faddr, mtod(nam, caddr_t), len); 229314564Sdim nam->m_len = len; 230321369Sdim return 0; 231327952Sdim} 232198090Srdivacky 233341825Sdim/* pru_rcvd is EOPNOTSUPP */ 234353358Sdim/* pru_rcvoob is EOPNOTSUPP */ 235198090Srdivacky 236198090Srdivackystatic int 237198090Srdivackyraw_usend(struct socket *so, int flags, struct mbuf *m, 238 struct mbuf *nam, struct mbuf *control, struct proc *p) 239{ 240 int error; 241 struct rawcb *rp = sotorawcb(so); 242 243 if (rp == 0) { 244 error = EINVAL; 245 goto release; 246 } 247 248 if (flags & PRUS_OOB) { 249 error = EOPNOTSUPP; 250 goto release; 251 } 252 253 if (control && control->m_len) { 254 error = EOPNOTSUPP; 255 goto release; 256 } 257 if (nam) { 258 if (rp->rcb_faddr) { 259 error = EISCONN; 260 goto release; 261 } 262 rp->rcb_faddr = mtod(nam, struct sockaddr *); 263 } else if (rp->rcb_faddr == 0) { 264 error = ENOTCONN; 265 goto release; 266 } 267 error = (*so->so_proto->pr_output)(m, so); 268 m = NULL; 269 if (nam) 270 rp->rcb_faddr = 0; 271release: 272 if (m != NULL) 273 m_freem(m); 274 return (error); 275} 276 277/* pru_sense is null */ 278 279static int 280raw_ushutdown(struct socket *so) 281{ 282 struct rawcb *rp = sotorawcb(so); 283 284 if (rp == 0) 285 return EINVAL; 286 socantsendmore(so); 287 return 0; 288} 289 290static int 291raw_usockaddr(struct socket *so, struct mbuf *nam) 292{ 293 struct rawcb *rp = sotorawcb(so); 294 unsigned len; 295 296 if (rp == 0) 297 return EINVAL; 298 if (rp->rcb_laddr == 0) 299 return EINVAL; 300 len = rp->rcb_laddr->sa_len; 301 bcopy((caddr_t)rp->rcb_laddr, mtod(nam, caddr_t), len); 302 nam->m_len = len; 303 return 0; 304} 305 306struct pr_usrreqs raw_usrreqs = { 307 raw_uabort, pru_accept_notsupp, raw_uattach, raw_ubind, raw_uconnect, 308 pru_connect2_notsupp, pru_control_notsupp, raw_udetach, 309 raw_udisconnect, pru_listen_notsupp, raw_upeeraddr, pru_rcvd_notsupp, 310 pru_rcvoob_notsupp, raw_usend, pru_sense_null, raw_ushutdown, 311 raw_usockaddr, sosend, soreceive, soselect 312}; 313