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