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