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.7 (Berkeley) 09/16/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 #if defined(INET) || defined(BBNNET) 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 #ifdef PUP 126 /* 127 * Curious, we convert PUP address format to internet 128 * to allow us to verify we're asking for an Ethernet 129 * interface. This is wrong, but things are heavily 130 * oriented towards the internet addressing scheme, and 131 * converting internet to PUP would be very expensive. 132 */ 133 case AF_PUP: { 134 struct sockaddr_pup *spup = (struct sockaddr_pup *)addr; 135 struct sockaddr_in inpup; 136 137 bzero((caddr_t)&inpup, (unsigned)sizeof(inpup)); 138 inpup.sin_family = AF_INET; 139 inpup.sin_addr = in_makeaddr(spup->spup_net, spup->spup_host); 140 if (inpup.sin_addr.s_addr && 141 ifa_ifwithaddr((struct sockaddr *)&inpup) == 0) 142 return (EADDRNOTAVAIL); 143 break; 144 } 145 #endif 146 147 default: 148 return (EAFNOSUPPORT); 149 } 150 /* END DUBIOUS */ 151 rp = sotorawcb(so); 152 bcopy((caddr_t)addr, (caddr_t)&rp->rcb_laddr, sizeof (*addr)); 153 rp->rcb_flags |= RAW_LADDR; 154 return (0); 155 } 156 157 /* 158 * Associate a peer's address with a 159 * raw connection block. 160 */ 161 raw_connaddr(rp, nam) 162 struct rawcb *rp; 163 struct mbuf *nam; 164 { 165 struct sockaddr *addr = mtod(nam, struct sockaddr *); 166 167 bcopy((caddr_t)addr, (caddr_t)&rp->rcb_faddr, sizeof(*addr)); 168 rp->rcb_flags |= RAW_FADDR; 169 } 170