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