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.6 (Berkeley) 06/27/88 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 /* 46 * Allocate a control block and a nominal amount 47 * of buffer space for the socket. 48 */ 49 raw_attach(so, proto) 50 register struct socket *so; 51 int proto; 52 { 53 struct mbuf *m; 54 register struct rawcb *rp; 55 56 m = m_getclr(M_DONTWAIT, MT_PCB); 57 if (m == 0) 58 return (ENOBUFS); 59 if (sbreserve(&so->so_snd, (u_long) RAWSNDQ) == 0) 60 goto bad; 61 if (sbreserve(&so->so_rcv, (u_long) RAWRCVQ) == 0) 62 goto bad2; 63 rp = mtod(m, struct rawcb *); 64 rp->rcb_socket = so; 65 so->so_pcb = (caddr_t)rp; 66 rp->rcb_pcb = 0; 67 rp->rcb_proto.sp_family = so->so_proto->pr_domain->dom_family; 68 rp->rcb_proto.sp_protocol = proto; 69 insque(rp, &rawcb); 70 return (0); 71 bad2: 72 sbrelease(&so->so_snd); 73 bad: 74 (void) m_free(m); 75 return (ENOBUFS); 76 } 77 78 /* 79 * Detach the raw connection block and discard 80 * socket resources. 81 */ 82 raw_detach(rp) 83 register struct rawcb *rp; 84 { 85 struct socket *so = rp->rcb_socket; 86 87 if (rp->rcb_route.ro_rt) 88 rtfree(rp->rcb_route.ro_rt); 89 so->so_pcb = 0; 90 sofree(so); 91 remque(rp); 92 if (rp->rcb_options) 93 m_freem(rp->rcb_options); 94 m_freem(dtom(rp)); 95 } 96 97 /* 98 * Disconnect and possibly release resources. 99 */ 100 raw_disconnect(rp) 101 struct rawcb *rp; 102 { 103 104 rp->rcb_flags &= ~RAW_FADDR; 105 if (rp->rcb_socket->so_state & SS_NOFDREF) 106 raw_detach(rp); 107 } 108 109 raw_bind(so, nam) 110 register struct socket *so; 111 struct mbuf *nam; 112 { 113 struct sockaddr *addr = mtod(nam, struct sockaddr *); 114 register struct rawcb *rp; 115 116 if (ifnet == 0) 117 return (EADDRNOTAVAIL); 118 /* BEGIN DUBIOUS */ 119 /* 120 * Should we verify address not already in use? 121 * Some say yes, others no. 122 */ 123 switch (addr->sa_family) { 124 125 #ifdef INET 126 case AF_IMPLINK: 127 case AF_INET: { 128 if (((struct sockaddr_in *)addr)->sin_addr.s_addr && 129 ifa_ifwithaddr(addr) == 0) 130 return (EADDRNOTAVAIL); 131 break; 132 } 133 #endif 134 135 default: 136 return (EAFNOSUPPORT); 137 } 138 /* END DUBIOUS */ 139 rp = sotorawcb(so); 140 bcopy((caddr_t)addr, (caddr_t)&rp->rcb_laddr, sizeof (*addr)); 141 rp->rcb_flags |= RAW_LADDR; 142 return (0); 143 } 144 145 /* 146 * Associate a peer's address with a 147 * raw connection block. 148 */ 149 raw_connaddr(rp, nam) 150 struct rawcb *rp; 151 struct mbuf *nam; 152 { 153 struct sockaddr *addr = mtod(nam, struct sockaddr *); 154 155 bcopy((caddr_t)addr, (caddr_t)&rp->rcb_faddr, sizeof(*addr)); 156 rp->rcb_flags |= RAW_FADDR; 157 } 158