|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1980, 1986 Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms are permitted ! 6: * provided that the above copyright notice and this paragraph are ! 7: * duplicated in all such forms and that any documentation, ! 8: * advertising materials, and other materials related to such ! 9: * distribution and use acknowledge that the software was developed ! 10: * by the University of California, Berkeley. The name of the ! 11: * University may not be used to endorse or promote products derived ! 12: * from this software without specific prior written permission. ! 13: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR ! 14: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED ! 15: * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 16: * ! 17: * @(#)raw_usrreq.c 7.4 (Berkeley) 6/27/88 ! 18: */ ! 19: ! 20: #include "param.h" ! 21: #include "mbuf.h" ! 22: #include "domain.h" ! 23: #include "protosw.h" ! 24: #include "socket.h" ! 25: #include "socketvar.h" ! 26: #include "errno.h" ! 27: ! 28: #include "if.h" ! 29: #include "route.h" ! 30: #include "netisr.h" ! 31: #include "raw_cb.h" ! 32: ! 33: #include "../machine/mtpr.h" ! 34: ! 35: /* ! 36: * Initialize raw connection block q. ! 37: */ ! 38: raw_init() ! 39: { ! 40: ! 41: rawcb.rcb_next = rawcb.rcb_prev = &rawcb; ! 42: rawintrq.ifq_maxlen = IFQ_MAXLEN; ! 43: } ! 44: ! 45: /* ! 46: * Raw protocol interface. ! 47: */ ! 48: raw_input(m0, proto, src, dst) ! 49: struct mbuf *m0; ! 50: struct sockproto *proto; ! 51: struct sockaddr *src, *dst; ! 52: { ! 53: register struct mbuf *m; ! 54: struct raw_header *rh; ! 55: int s; ! 56: ! 57: /* ! 58: * Rip off an mbuf for a generic header. ! 59: */ ! 60: m = m_get(M_DONTWAIT, MT_HEADER); ! 61: if (m == 0) { ! 62: m_freem(m0); ! 63: return; ! 64: } ! 65: m->m_next = m0; ! 66: m->m_len = sizeof(struct raw_header); ! 67: rh = mtod(m, struct raw_header *); ! 68: rh->raw_dst = *dst; ! 69: rh->raw_src = *src; ! 70: rh->raw_proto = *proto; ! 71: ! 72: /* ! 73: * Header now contains enough info to decide ! 74: * which socket to place packet in (if any). ! 75: * Queue it up for the raw protocol process ! 76: * running at software interrupt level. ! 77: */ ! 78: s = splimp(); ! 79: if (IF_QFULL(&rawintrq)) ! 80: m_freem(m); ! 81: else ! 82: IF_ENQUEUE(&rawintrq, m); ! 83: splx(s); ! 84: schednetisr(NETISR_RAW); ! 85: } ! 86: ! 87: /* ! 88: * Raw protocol input routine. Process packets entered ! 89: * into the queue at interrupt time. Find the socket ! 90: * associated with the packet(s) and move them over. If ! 91: * nothing exists for this packet, drop it. ! 92: */ ! 93: rawintr() ! 94: { ! 95: int s; ! 96: struct mbuf *m; ! 97: register struct rawcb *rp; ! 98: register struct raw_header *rh; ! 99: struct socket *last; ! 100: ! 101: next: ! 102: s = splimp(); ! 103: IF_DEQUEUE(&rawintrq, m); ! 104: splx(s); ! 105: if (m == 0) ! 106: return; ! 107: rh = mtod(m, struct raw_header *); ! 108: last = 0; ! 109: for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) { ! 110: if (rp->rcb_proto.sp_family != rh->raw_proto.sp_family) ! 111: continue; ! 112: if (rp->rcb_proto.sp_protocol && ! 113: rp->rcb_proto.sp_protocol != rh->raw_proto.sp_protocol) ! 114: continue; ! 115: /* ! 116: * We assume the lower level routines have ! 117: * placed the address in a canonical format ! 118: * suitable for a structure comparison. ! 119: */ ! 120: #define equal(a1, a2) \ ! 121: (bcmp((caddr_t)&(a1), (caddr_t)&(a2), sizeof (struct sockaddr)) == 0) ! 122: if ((rp->rcb_flags & RAW_LADDR) && ! 123: !equal(rp->rcb_laddr, rh->raw_dst)) ! 124: continue; ! 125: if ((rp->rcb_flags & RAW_FADDR) && ! 126: !equal(rp->rcb_faddr, rh->raw_src)) ! 127: continue; ! 128: if (last) { ! 129: struct mbuf *n; ! 130: if (n = m_copy(m->m_next, 0, (int)M_COPYALL)) { ! 131: if (sbappendaddr(&last->so_rcv, &rh->raw_src, ! 132: n, (struct mbuf *)0) == 0) ! 133: /* should notify about lost packet */ ! 134: m_freem(n); ! 135: else ! 136: sorwakeup(last); ! 137: } ! 138: } ! 139: last = rp->rcb_socket; ! 140: } ! 141: if (last) { ! 142: if (sbappendaddr(&last->so_rcv, &rh->raw_src, ! 143: m->m_next, (struct mbuf *)0) == 0) ! 144: m_freem(m->m_next); ! 145: else ! 146: sorwakeup(last); ! 147: (void) m_free(m); /* header */ ! 148: } else ! 149: m_freem(m); ! 150: goto next; ! 151: } ! 152: ! 153: /*ARGSUSED*/ ! 154: raw_ctlinput(cmd, arg) ! 155: int cmd; ! 156: struct sockaddr *arg; ! 157: { ! 158: ! 159: if (cmd < 0 || cmd > PRC_NCMDS) ! 160: return; ! 161: /* INCOMPLETE */ ! 162: } ! 163: ! 164: /*ARGSUSED*/ ! 165: raw_usrreq(so, req, m, nam, rights) ! 166: struct socket *so; ! 167: int req; ! 168: struct mbuf *m, *nam, *rights; ! 169: { ! 170: register struct rawcb *rp = sotorawcb(so); ! 171: register int error = 0; ! 172: ! 173: if (req == PRU_CONTROL) ! 174: return (EOPNOTSUPP); ! 175: if (rights && rights->m_len) { ! 176: error = EOPNOTSUPP; ! 177: goto release; ! 178: } ! 179: if (rp == 0 && req != PRU_ATTACH) { ! 180: error = EINVAL; ! 181: goto release; ! 182: } ! 183: switch (req) { ! 184: ! 185: /* ! 186: * Allocate a raw control block and fill in the ! 187: * necessary info to allow packets to be routed to ! 188: * the appropriate raw interface routine. ! 189: */ ! 190: case PRU_ATTACH: ! 191: if ((so->so_state & SS_PRIV) == 0) { ! 192: error = EACCES; ! 193: break; ! 194: } ! 195: if (rp) { ! 196: error = EINVAL; ! 197: break; ! 198: } ! 199: error = raw_attach(so, (int)nam); ! 200: break; ! 201: ! 202: /* ! 203: * Destroy state just before socket deallocation. ! 204: * Flush data or not depending on the options. ! 205: */ ! 206: case PRU_DETACH: ! 207: if (rp == 0) { ! 208: error = ENOTCONN; ! 209: break; ! 210: } ! 211: raw_detach(rp); ! 212: break; ! 213: ! 214: /* ! 215: * If a socket isn't bound to a single address, ! 216: * the raw input routine will hand it anything ! 217: * within that protocol family (assuming there's ! 218: * nothing else around it should go to). ! 219: */ ! 220: case PRU_CONNECT: ! 221: if (rp->rcb_flags & RAW_FADDR) { ! 222: error = EISCONN; ! 223: break; ! 224: } ! 225: raw_connaddr(rp, nam); ! 226: soisconnected(so); ! 227: break; ! 228: ! 229: case PRU_CONNECT2: ! 230: error = EOPNOTSUPP; ! 231: goto release; ! 232: ! 233: case PRU_BIND: ! 234: if (rp->rcb_flags & RAW_LADDR) { ! 235: error = EINVAL; /* XXX */ ! 236: break; ! 237: } ! 238: error = raw_bind(so, nam); ! 239: break; ! 240: ! 241: case PRU_DISCONNECT: ! 242: if ((rp->rcb_flags & RAW_FADDR) == 0) { ! 243: error = ENOTCONN; ! 244: break; ! 245: } ! 246: raw_disconnect(rp); ! 247: soisdisconnected(so); ! 248: break; ! 249: ! 250: /* ! 251: * Mark the connection as being incapable of further input. ! 252: */ ! 253: case PRU_SHUTDOWN: ! 254: socantsendmore(so); ! 255: break; ! 256: ! 257: /* ! 258: * Ship a packet out. The appropriate raw output ! 259: * routine handles any massaging necessary. ! 260: */ ! 261: case PRU_SEND: ! 262: if (nam) { ! 263: if (rp->rcb_flags & RAW_FADDR) { ! 264: error = EISCONN; ! 265: break; ! 266: } ! 267: raw_connaddr(rp, nam); ! 268: } else if ((rp->rcb_flags & RAW_FADDR) == 0) { ! 269: error = ENOTCONN; ! 270: break; ! 271: } ! 272: error = (*so->so_proto->pr_output)(m, so); ! 273: m = NULL; ! 274: if (nam) ! 275: rp->rcb_flags &= ~RAW_FADDR; ! 276: break; ! 277: ! 278: case PRU_ABORT: ! 279: raw_disconnect(rp); ! 280: sofree(so); ! 281: soisdisconnected(so); ! 282: break; ! 283: ! 284: case PRU_SENSE: ! 285: /* ! 286: * stat: don't bother with a blocksize. ! 287: */ ! 288: return (0); ! 289: ! 290: /* ! 291: * Not supported. ! 292: */ ! 293: case PRU_RCVOOB: ! 294: case PRU_RCVD: ! 295: return(EOPNOTSUPP); ! 296: ! 297: case PRU_LISTEN: ! 298: case PRU_ACCEPT: ! 299: case PRU_SENDOOB: ! 300: error = EOPNOTSUPP; ! 301: break; ! 302: ! 303: case PRU_SOCKADDR: ! 304: bcopy((caddr_t)&rp->rcb_laddr, mtod(nam, caddr_t), ! 305: sizeof (struct sockaddr)); ! 306: nam->m_len = sizeof (struct sockaddr); ! 307: break; ! 308: ! 309: case PRU_PEERADDR: ! 310: bcopy((caddr_t)&rp->rcb_faddr, mtod(nam, caddr_t), ! 311: sizeof (struct sockaddr)); ! 312: nam->m_len = sizeof (struct sockaddr); ! 313: break; ! 314: ! 315: default: ! 316: panic("raw_usrreq"); ! 317: } ! 318: release: ! 319: if (m != NULL) ! 320: m_freem(m); ! 321: return (error); ! 322: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.