1 /* $NetBSD: raw_usrreq.c,v 1.15 2000/03/30 09:45:40 augustss 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/param.h> 39 #include <sys/mbuf.h> 40 #include <sys/domain.h> 41 #include <sys/protosw.h> 42 #include <sys/socket.h> 43 #include <sys/socketvar.h> 44 #include <sys/errno.h> 45 #include <sys/systm.h> 46 #include <sys/proc.h> 47 48 #include <net/if.h> 49 #include <net/route.h> 50 #include <net/netisr.h> 51 #include <net/raw_cb.h> 52 53 #include <machine/stdarg.h> 54 /* 55 * Initialize raw connection block q. 56 */ 57 void 58 raw_init() 59 { 60 61 LIST_INIT(&rawcb); 62 } 63 64 65 /* 66 * Raw protocol input routine. Find the socket 67 * associated with the packet(s) and move them over. If 68 * nothing exists for this packet, drop it. 69 */ 70 /* 71 * Raw protocol interface. 72 */ 73 void 74 #if __STDC__ 75 raw_input(struct mbuf *m0, ...) 76 #else 77 raw_input(m0, va_alist) 78 struct mbuf *m0; 79 va_dcl 80 #endif 81 { 82 struct rawcb *rp; 83 struct mbuf *m = m0; 84 int sockets = 0; 85 struct socket *last; 86 va_list ap; 87 struct sockproto *proto; 88 struct sockaddr *src, *dst; 89 90 va_start(ap, m0); 91 proto = va_arg(ap, struct sockproto *); 92 src = va_arg(ap, struct sockaddr *); 93 dst = va_arg(ap, struct sockaddr *); 94 va_end(ap); 95 96 last = 0; 97 for (rp = rawcb.lh_first; rp != 0; rp = rp->rcb_list.le_next) { 98 if (rp->rcb_proto.sp_family != proto->sp_family) 99 continue; 100 if (rp->rcb_proto.sp_protocol && 101 rp->rcb_proto.sp_protocol != proto->sp_protocol) 102 continue; 103 /* 104 * We assume the lower level routines have 105 * placed the address in a canonical format 106 * suitable for a structure comparison. 107 * 108 * Note that if the lengths are not the same 109 * the comparison will fail at the first byte. 110 */ 111 #define equal(a1, a2) \ 112 (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0) 113 if (rp->rcb_laddr && !equal(rp->rcb_laddr, dst)) 114 continue; 115 if (rp->rcb_faddr && !equal(rp->rcb_faddr, src)) 116 continue; 117 if (last) { 118 struct mbuf *n; 119 if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) { 120 if (sbappendaddr(&last->so_rcv, src, 121 n, (struct mbuf *)0) == 0) 122 /* should notify about lost packet */ 123 m_freem(n); 124 else { 125 sorwakeup(last); 126 sockets++; 127 } 128 } 129 } 130 last = rp->rcb_socket; 131 } 132 if (last) { 133 if (sbappendaddr(&last->so_rcv, src, 134 m, (struct mbuf *)0) == 0) 135 m_freem(m); 136 else { 137 sorwakeup(last); 138 sockets++; 139 } 140 } else 141 m_freem(m); 142 } 143 144 /*ARGSUSED*/ 145 void * 146 raw_ctlinput(cmd, arg, d) 147 int cmd; 148 struct sockaddr *arg; 149 void *d; 150 { 151 152 if (cmd < 0 || cmd > PRC_NCMDS) 153 return NULL; 154 return NULL; 155 /* INCOMPLETE */ 156 } 157 158 void 159 raw_setsockaddr(rp, nam) 160 struct rawcb *rp; 161 struct mbuf *nam; 162 { 163 164 nam->m_len = rp->rcb_laddr->sa_len; 165 bcopy(rp->rcb_laddr, mtod(nam, caddr_t), (size_t)nam->m_len); 166 } 167 168 void 169 raw_setpeeraddr(rp, nam) 170 struct rawcb *rp; 171 struct mbuf *nam; 172 { 173 174 nam->m_len = rp->rcb_faddr->sa_len; 175 bcopy(rp->rcb_faddr, mtod(nam, caddr_t), (size_t)nam->m_len); 176 } 177 178 /*ARGSUSED*/ 179 int 180 raw_usrreq(so, req, m, nam, control, p) 181 struct socket *so; 182 int req; 183 struct mbuf *m, *nam, *control; 184 struct proc *p; 185 { 186 struct rawcb *rp; 187 int s; 188 int error = 0; 189 190 if (req == PRU_CONTROL) 191 return (EOPNOTSUPP); 192 193 s = splsoftnet(); 194 rp = sotorawcb(so); 195 #ifdef DIAGNOSTIC 196 if (req != PRU_SEND && req != PRU_SENDOOB && control) 197 panic("raw_usrreq: unexpected control mbuf"); 198 #endif 199 if (rp == 0 && req != PRU_ATTACH) { 200 error = EINVAL; 201 goto release; 202 } 203 204 switch (req) { 205 206 /* 207 * Allocate a raw control block and fill in the 208 * necessary info to allow packets to be routed to 209 * the appropriate raw interface routine. 210 */ 211 case PRU_ATTACH: 212 if (p == 0 || (error = suser(p->p_ucred, &p->p_acflag))) { 213 error = EACCES; 214 break; 215 } 216 error = raw_attach(so, (int)(long)nam); 217 break; 218 219 /* 220 * Destroy state just before socket deallocation. 221 * Flush data or not depending on the options. 222 */ 223 case PRU_DETACH: 224 raw_detach(rp); 225 break; 226 227 /* 228 * If a socket isn't bound to a single address, 229 * the raw input routine will hand it anything 230 * within that protocol family (assuming there's 231 * nothing else around it should go to). 232 */ 233 case PRU_BIND: 234 case PRU_LISTEN: 235 case PRU_CONNECT: 236 case PRU_CONNECT2: 237 error = EOPNOTSUPP; 238 break; 239 240 case PRU_DISCONNECT: 241 soisdisconnected(so); 242 raw_disconnect(rp); 243 break; 244 245 /* 246 * Mark the connection as being incapable of further input. 247 */ 248 case PRU_SHUTDOWN: 249 socantsendmore(so); 250 break; 251 252 case PRU_RCVD: 253 error = EOPNOTSUPP; 254 break; 255 256 /* 257 * Ship a packet out. The appropriate raw output 258 * routine handles any massaging necessary. 259 */ 260 case PRU_SEND: 261 if (control && control->m_len) { 262 m_freem(control); 263 m_freem(m); 264 error = EINVAL; 265 break; 266 } 267 if (nam) { 268 if ((so->so_state & SS_ISCONNECTED) != 0) { 269 error = EISCONN; 270 goto die; 271 } 272 error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT, 273 (struct mbuf *)0, nam, (struct mbuf *)0, p); 274 if (error) { 275 die: 276 m_freem(m); 277 break; 278 } 279 } else { 280 if ((so->so_state & SS_ISCONNECTED) == 0) { 281 error = ENOTCONN; 282 goto die; 283 } 284 } 285 error = (*so->so_proto->pr_output)(m, so); 286 if (nam) 287 raw_disconnect(rp); 288 break; 289 290 case PRU_SENSE: 291 /* 292 * stat: don't bother with a blocksize. 293 */ 294 return (0); 295 296 /* 297 * Not supported. 298 */ 299 case PRU_RCVOOB: 300 error = EOPNOTSUPP; 301 break; 302 303 case PRU_SENDOOB: 304 m_freem(control); 305 m_freem(m); 306 error = EOPNOTSUPP; 307 break; 308 309 case PRU_SOCKADDR: 310 if (rp->rcb_laddr == 0) { 311 error = EINVAL; 312 break; 313 } 314 raw_setsockaddr(rp, nam); 315 break; 316 317 case PRU_PEERADDR: 318 if (rp->rcb_faddr == 0) { 319 error = ENOTCONN; 320 break; 321 } 322 raw_setpeeraddr(rp, nam); 323 break; 324 325 default: 326 panic("raw_usrreq"); 327 } 328 329 release: 330 splx(s); 331 return (error); 332 } 333