+ if (op == PRCO_SETOPT && *m)
+ (void)m_free(*m);
+ return (error);
+}
+
+/*ARGSUSED*/
+rip_usrreq(so, req, m, nam, rights, control)
+ register struct socket *so;
+ int req;
+ struct mbuf *m, *nam, *rights, *control;
+{
+ register int error = 0;
+ register struct raw_inpcb *rp = sotorawinpcb(so);
+
+ switch (req) {
+
+ case PRU_ATTACH:
+ if (rp)
+ panic("rip_attach");
+ MALLOC(rp, struct raw_inpcb *, sizeof *rp, M_PCB, M_WAITOK);
+ if (rp == 0)
+ return (ENOBUFS);
+ bzero((caddr_t)rp, sizeof *rp);
+ so->so_pcb = (caddr_t)rp;
+ break;
+
+ case PRU_DETACH:
+ if (rp == 0)
+ panic("rip_detach");
+ if (rp->rinp_options)
+ m_freem(rp->rinp_options);
+ if (rp->rinp_route.ro_rt)
+ RTFREE(rp->rinp_route.ro_rt);
+ if (rp->rinp_rcb.rcb_laddr)
+ rp->rinp_rcb.rcb_laddr = 0;
+ break;
+
+ case PRU_BIND:
+ {
+ struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *);
+
+ if (nam->m_len != sizeof(*addr))
+ return (EINVAL);
+ if ((ifnet == 0) ||
+ ((addr->sin_family != AF_INET) &&
+ (addr->sin_family != AF_IMPLINK)) ||
+ (addr->sin_addr.s_addr &&
+ ifa_ifwithaddr((struct sockaddr *)addr) == 0))
+ return (EADDRNOTAVAIL);
+ rp->rinp_rcb.rcb_laddr = (struct sockaddr *)&rp->rinp_laddr;
+ rp->rinp_laddr = *addr;
+ return (0);
+ }
+ case PRU_CONNECT:
+ {
+ struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *);
+
+ if (nam->m_len != sizeof(*addr))
+ return (EINVAL);
+ if (ifnet == 0)
+ return (EADDRNOTAVAIL);
+ if ((addr->sin_family != AF_INET) &&
+ (addr->sin_family != AF_IMPLINK))
+ return (EAFNOSUPPORT);
+ rp->rinp_rcb.rcb_faddr = (struct sockaddr *)&rp->rinp_faddr;
+ rp->rinp_laddr = *addr;
+ soisconnected(so);
+ return (0);
+ }
+ }
+ error = raw_usrreq(so, req, m, nam, rights, control);
+
+ if (error && (req == PRU_ATTACH) && so->so_pcb)
+ free(so->so_pcb, M_PCB);