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