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