+ if (rp == 0 && req != PRU_ATTACH)
+ return (EINVAL);
+
+ switch (req) {
+
+ /*
+ * Allocate a raw control block and fill in the
+ * necessary info to allow packets to be routed to
+ * the appropriate raw interface routine.
+ */
+ case PRU_ATTACH:
+ if ((so->so_state & SS_PRIV) == 0)
+ return (EACCES);
+ if (rp)
+ return (EINVAL);
+ error = raw_attach(so, (struct sockaddr *)addr);
+ break;
+
+ /*
+ * Destroy state just before socket deallocation.
+ * Flush data or not depending on the options.
+ */
+ case PRU_DETACH:
+ if (rp == 0)
+ return (ENOTCONN);
+ raw_detach(rp);
+ break;
+
+ /*
+ * If a socket isn't bound to a single address,
+ * the raw input routine will hand it anything
+ * within that protocol family (assuming there's
+ * nothing else around it should go to).
+ */
+ case PRU_CONNECT:
+ if (rp->rcb_flags & RAW_FADDR)
+ return (EISCONN);
+ raw_connaddr(rp, (struct sockaddr *)addr);
+ soisconnected(so);
+ break;
+
+ case PRU_DISCONNECT:
+ if ((rp->rcb_flags & RAW_FADDR) == 0)
+ return (ENOTCONN);
+ raw_disconnect(rp);
+ soisdisconnected(so);
+ break;
+
+ /*
+ * Mark the connection as being incapable of further input.
+ */
+ case PRU_SHUTDOWN:
+ socantsendmore(so);
+ break;
+
+ /*
+ * Ship a packet out. The appropriate raw output
+ * routine handles any massaging necessary.
+ */
+ case PRU_SEND:
+ if (addr) {
+ if (rp->rcb_flags & RAW_FADDR)
+ return (EISCONN);
+ raw_connaddr(rp, (struct sockaddr *)addr);
+ } else if ((rp->rcb_flags & RAW_FADDR) == 0)
+ return (ENOTCONN);
+ error = (*so->so_proto->pr_output)(m, so);
+ if (addr)
+ rp->rcb_flags &= ~RAW_FADDR;
+ break;
+
+ case PRU_ABORT:
+ raw_disconnect(rp);
+ sofree(so);
+ soisdisconnected(so);
+ break;
+
+ /*
+ * Not supported.
+ */
+ case PRU_ACCEPT:
+ case PRU_RCVD:
+ case PRU_CONTROL:
+ case PRU_SENSE:
+ case PRU_RCVOOB:
+ case PRU_SENDOOB:
+ error = EOPNOTSUPP;
+ break;
+
+ case PRU_SOCKADDR:
+ bcopy(addr, (caddr_t)&rp->rcb_laddr, sizeof (struct sockaddr));
+ break;