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