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_cb.c 7.3 (Berkeley) 10/28/86 7 */ 8 9 #include "param.h" 10 #include "systm.h" 11 #include "mbuf.h" 12 #include "socket.h" 13 #include "socketvar.h" 14 #include "domain.h" 15 #include "protosw.h" 16 #include "errno.h" 17 18 #include "if.h" 19 #include "route.h" 20 #include "raw_cb.h" 21 #include "../netinet/in.h" 22 23 #include "../machine/mtpr.h" 24 25 /* 26 * Routines to manage the raw protocol control blocks. 27 * 28 * TODO: 29 * hash lookups by protocol family/protocol + address family 30 * take care of unique address problems per AF? 31 * redo address binding to allow wildcards 32 */ 33 34 /* 35 * Allocate a control block and a nominal amount 36 * of buffer space for the socket. 37 */ 38 raw_attach(so, proto) 39 register struct socket *so; 40 int proto; 41 { 42 struct mbuf *m; 43 register struct rawcb *rp; 44 45 m = m_getclr(M_DONTWAIT, MT_PCB); 46 if (m == 0) 47 return (ENOBUFS); 48 if (sbreserve(&so->so_snd, RAWSNDQ) == 0) 49 goto bad; 50 if (sbreserve(&so->so_rcv, RAWRCVQ) == 0) 51 goto bad2; 52 rp = mtod(m, struct rawcb *); 53 rp->rcb_socket = so; 54 so->so_pcb = (caddr_t)rp; 55 rp->rcb_pcb = 0; 56 rp->rcb_proto.sp_family = so->so_proto->pr_domain->dom_family; 57 rp->rcb_proto.sp_protocol = proto; 58 insque(rp, &rawcb); 59 return (0); 60 bad2: 61 sbrelease(&so->so_snd); 62 bad: 63 (void) m_free(m); 64 return (ENOBUFS); 65 } 66 67 /* 68 * Detach the raw connection block and discard 69 * socket resources. 70 */ 71 raw_detach(rp) 72 register struct rawcb *rp; 73 { 74 struct socket *so = rp->rcb_socket; 75 76 if (rp->rcb_route.ro_rt) 77 rtfree(rp->rcb_route.ro_rt); 78 so->so_pcb = 0; 79 sofree(so); 80 remque(rp); 81 if (rp->rcb_options) 82 m_freem(rp->rcb_options); 83 m_freem(dtom(rp)); 84 } 85 86 /* 87 * Disconnect and possibly release resources. 88 */ 89 raw_disconnect(rp) 90 struct rawcb *rp; 91 { 92 93 rp->rcb_flags &= ~RAW_FADDR; 94 if (rp->rcb_socket->so_state & SS_NOFDREF) 95 raw_detach(rp); 96 } 97 98 raw_bind(so, nam) 99 register struct socket *so; 100 struct mbuf *nam; 101 { 102 struct sockaddr *addr = mtod(nam, struct sockaddr *); 103 register struct rawcb *rp; 104 105 if (ifnet == 0) 106 return (EADDRNOTAVAIL); 107 /* BEGIN DUBIOUS */ 108 /* 109 * Should we verify address not already in use? 110 * Some say yes, others no. 111 */ 112 switch (addr->sa_family) { 113 114 #ifdef INET 115 case AF_IMPLINK: 116 case AF_INET: { 117 if (((struct sockaddr_in *)addr)->sin_addr.s_addr && 118 ifa_ifwithaddr(addr) == 0) 119 return (EADDRNOTAVAIL); 120 break; 121 } 122 #endif 123 124 default: 125 return (EAFNOSUPPORT); 126 } 127 /* END DUBIOUS */ 128 rp = sotorawcb(so); 129 bcopy((caddr_t)addr, (caddr_t)&rp->rcb_laddr, sizeof (*addr)); 130 rp->rcb_flags |= RAW_LADDR; 131 return (0); 132 } 133 134 /* 135 * Associate a peer's address with a 136 * raw connection block. 137 */ 138 raw_connaddr(rp, nam) 139 struct rawcb *rp; 140 struct mbuf *nam; 141 { 142 struct sockaddr *addr = mtod(nam, struct sockaddr *); 143 144 bcopy((caddr_t)addr, (caddr_t)&rp->rcb_faddr, sizeof(*addr)); 145 rp->rcb_flags |= RAW_FADDR; 146 } 147