1 /* $NetBSD: raw_usrreq.c,v 1.17 2001/11/12 23:49:48 lukem Exp $ */ 2 3 /* 4 * Copyright (c) 1980, 1986, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * @(#)raw_usrreq.c 8.1 (Berkeley) 6/10/93 36 */ 37 38 #include <sys/cdefs.h> 39 __KERNEL_RCSID(0, "$NetBSD: raw_usrreq.c,v 1.17 2001/11/12 23:49:48 lukem Exp $"); 40 41 #include <sys/param.h> 42 #include <sys/mbuf.h> 43 #include <sys/domain.h> 44 #include <sys/protosw.h> 45 #include <sys/socket.h> 46 #include <sys/socketvar.h> 47 #include <sys/errno.h> 48 #include <sys/systm.h> 49 #include <sys/proc.h> 50 51 #include <net/if.h> 52 #include <net/route.h> 53 #include <net/netisr.h> 54 #include <net/raw_cb.h> 55 56 #include <machine/stdarg.h> 57 /* 58 * Initialize raw connection block q. 59 */ 60 void 61 raw_init() 62 { 63 64 LIST_INIT(&rawcb); 65 } 66 67 68 /* 69 * Raw protocol input routine. Find the socket 70 * associated with the packet(s) and move them over. If 71 * nothing exists for this packet, drop it. 72 */ 73 /* 74 * Raw protocol interface. 75 */ 76 void 77 #if __STDC__ 78 raw_input(struct mbuf *m0, ...) 79 #else 80 raw_input(m0, va_alist) 81 struct mbuf *m0; 82 va_dcl 83 #endif 84 { 85 struct rawcb *rp; 86 struct mbuf *m = m0; 87 int sockets = 0; 88 struct socket *last; 89 va_list ap; 90 struct sockproto *proto; 91 struct sockaddr *src, *dst; 92 93 va_start(ap, m0); 94 proto = va_arg(ap, struct sockproto *); 95 src = va_arg(ap, struct sockaddr *); 96 dst = va_arg(ap, struct sockaddr *); 97 va_end(ap); 98 99 last = 0; 100 LIST_FOREACH(rp, &rawcb, rcb_list) { 101 if (rp->rcb_proto.sp_family != proto->sp_family) 102 continue; 103 if (rp->rcb_proto.sp_protocol && 104 rp->rcb_proto.sp_protocol != proto->sp_protocol) 105 continue; 106 /* 107 * We assume the lower level routines have 108 * placed the address in a canonical format 109 * suitable for a structure comparison. 110 * 111 * Note that if the lengths are not the same 112 * the comparison will fail at the first byte. 113 */ 114 #define equal(a1, a2) \ 115 (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0) 116 if (rp->rcb_laddr && !equal(rp->rcb_laddr, dst)) 117 continue; 118 if (rp->rcb_faddr && !equal(rp->rcb_faddr, src)) 119 continue; 120 if (last) { 121 struct mbuf *n; 122 if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) { 123 if (sbappendaddr(&last->so_rcv, src, 124 n, (struct mbuf *)0) == 0) 125 /* should notify about lost packet */ 126 m_freem(n); 127 else { 128 sorwakeup(last); 129 sockets++; 130 } 131 } 132 } 133 last = rp->rcb_socket; 134 } 135 if (last) { 136 if (sbappendaddr(&last->so_rcv, src, 137 m, (struct mbuf *)0) == 0) 138 m_freem(m); 139 else { 140 sorwakeup(last); 141 sockets++; 142 } 143 } else 144 m_freem(m); 145 } 146 147 /*ARGSUSED*/ 148 void * 149 raw_ctlinput(cmd, arg, d) 150 int cmd; 151 struct sockaddr *arg; 152 void *d; 153 { 154 155 if (cmd < 0 || cmd > PRC_NCMDS) 156 return NULL; 157 return NULL; 158 /* INCOMPLETE */ 159 } 160 161 void 162 raw_setsockaddr(rp, nam) 163 struct rawcb *rp; 164 struct mbuf *nam; 165 { 166 167 nam->m_len = rp->rcb_laddr->sa_len; 168 bcopy(rp->rcb_laddr, mtod(nam, caddr_t), (size_t)nam->m_len); 169 } 170 171 void 172 raw_setpeeraddr(rp, nam) 173 struct rawcb *rp; 174 struct mbuf *nam; 175 { 176 177 nam->m_len = rp->rcb_faddr->sa_len; 178 bcopy(rp->rcb_faddr, mtod(nam, caddr_t), (size_t)nam->m_len); 179 } 180 181 /*ARGSUSED*/ 182 int 183 raw_usrreq(so, req, m, nam, control, p) 184 struct socket *so; 185 int req; 186 struct mbuf *m, *nam, *control; 187 struct proc *p; 188 { 189 struct rawcb *rp; 190 int s; 191 int error = 0; 192 193 if (req == PRU_CONTROL) 194 return (EOPNOTSUPP); 195 196 s = splsoftnet(); 197 rp = sotorawcb(so); 198 #ifdef DIAGNOSTIC 199 if (req != PRU_SEND && req != PRU_SENDOOB && control) 200 panic("raw_usrreq: unexpected control mbuf"); 201 #endif 202 if (rp == 0 && req != PRU_ATTACH) { 203 error = EINVAL; 204 goto release; 205 } 206 207 switch (req) { 208 209 /* 210 * Allocate a raw control block and fill in the 211 * necessary info to allow packets to be routed to 212 * the appropriate raw interface routine. 213 */ 214 case PRU_ATTACH: 215 if (p == 0 || (error = suser(p->p_ucred, &p->p_acflag))) { 216 error = EACCES; 217 break; 218 } 219 error = raw_attach(so, (int)(long)nam); 220 break; 221 222 /* 223 * Destroy state just before socket deallocation. 224 * Flush data or not depending on the options. 225 */ 226 case PRU_DETACH: 227 raw_detach(rp); 228 break; 229 230 /* 231 * If a socket isn't bound to a single address, 232 * the raw input routine will hand it anything 233 * within that protocol family (assuming there's 234 * nothing else around it should go to). 235 */ 236 case PRU_BIND: 237 case PRU_LISTEN: 238 case PRU_CONNECT: 239 case PRU_CONNECT2: 240 error = EOPNOTSUPP; 241 break; 242 243 case PRU_DISCONNECT: 244 soisdisconnected(so); 245 raw_disconnect(rp); 246 break; 247 248 /* 249 * Mark the connection as being incapable of further input. 250 */ 251 case PRU_SHUTDOWN: 252 socantsendmore(so); 253 break; 254 255 case PRU_RCVD: 256 error = EOPNOTSUPP; 257 break; 258 259 /* 260 * Ship a packet out. The appropriate raw output 261 * routine handles any massaging necessary. 262 */ 263 case PRU_SEND: 264 if (control && control->m_len) { 265 m_freem(control); 266 m_freem(m); 267 error = EINVAL; 268 break; 269 } 270 if (nam) { 271 if ((so->so_state & SS_ISCONNECTED) != 0) { 272 error = EISCONN; 273 goto die; 274 } 275 error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT, 276 (struct mbuf *)0, nam, (struct mbuf *)0, p); 277 if (error) { 278 die: 279 m_freem(m); 280 break; 281 } 282 } else { 283 if ((so->so_state & SS_ISCONNECTED) == 0) { 284 error = ENOTCONN; 285 goto die; 286 } 287 } 288 error = (*so->so_proto->pr_output)(m, so); 289 if (nam) 290 raw_disconnect(rp); 291 break; 292 293 case PRU_SENSE: 294 /* 295 * stat: don't bother with a blocksize. 296 */ 297 return (0); 298 299 /* 300 * Not supported. 301 */ 302 case PRU_RCVOOB: 303 error = EOPNOTSUPP; 304 break; 305 306 case PRU_SENDOOB: 307 m_freem(control); 308 m_freem(m); 309 error = EOPNOTSUPP; 310 break; 311 312 case PRU_SOCKADDR: 313 if (rp->rcb_laddr == 0) { 314 error = EINVAL; 315 break; 316 } 317 raw_setsockaddr(rp, nam); 318 break; 319 320 case PRU_PEERADDR: 321 if (rp->rcb_faddr == 0) { 322 error = ENOTCONN; 323 break; 324 } 325 raw_setpeeraddr(rp, nam); 326 break; 327 328 default: 329 panic("raw_usrreq"); 330 } 331 332 release: 333 splx(s); 334 return (error); 335 } 336