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