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.6 (Berkeley) 06/08/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 so->so_pcb = 0; 80 sofree(so); 81 remque(rp); 82 m_freem(dtom(rp)); 83 } 84 85 /* 86 * Disconnect and possibly release resources. 87 */ 88 raw_disconnect(rp) 89 struct rawcb *rp; 90 { 91 92 rp->rcb_flags &= ~RAW_FADDR; 93 if (rp->rcb_socket->so_state & SS_NOFDREF) 94 raw_detach(rp); 95 } 96 97 raw_bind(so, nam) 98 register struct socket *so; 99 struct mbuf *nam; 100 { 101 struct sockaddr *addr = mtod(nam, struct sockaddr *); 102 register struct rawcb *rp; 103 104 if (ifnet == 0) 105 return (EADDRNOTAVAIL); 106 /* BEGIN DUBIOUS */ 107 /* 108 * Should we verify address not already in use? 109 * Some say yes, others no. 110 */ 111 switch (addr->sa_family) { 112 113 #ifdef INET 114 case AF_IMPLINK: 115 case AF_INET: { 116 if (((struct sockaddr_in *)addr)->sin_addr.s_addr && 117 ifa_ifwithaddr(addr) == 0) 118 return (EADDRNOTAVAIL); 119 break; 120 } 121 #endif 122 123 #ifdef PUP 124 /* 125 * Curious, we convert PUP address format to internet 126 * to allow us to verify we're asking for an Ethernet 127 * interface. This is wrong, but things are heavily 128 * oriented towards the internet addressing scheme, and 129 * converting internet to PUP would be very expensive. 130 */ 131 case AF_PUP: { 132 struct sockaddr_pup *spup = (struct sockaddr_pup *)addr; 133 struct sockaddr_in inpup; 134 135 bzero((caddr_t)&inpup, (unsigned)sizeof(inpup)); 136 inpup.sin_family = AF_INET; 137 inpup.sin_addr = in_makeaddr(spup->spup_net, spup->spup_host); 138 if (inpup.sin_addr.s_addr && 139 ifa_ifwithaddr((struct sockaddr *)&inpup) == 0) 140 return (EADDRNOTAVAIL); 141 break; 142 } 143 #endif 144 145 default: 146 return (EAFNOSUPPORT); 147 } 148 /* END DUBIOUS */ 149 rp = sotorawcb(so); 150 bcopy((caddr_t)addr, (caddr_t)&rp->rcb_laddr, sizeof (*addr)); 151 rp->rcb_flags |= RAW_LADDR; 152 return (0); 153 } 154 155 /* 156 * Associate a peer's address with a 157 * raw connection block. 158 */ 159 raw_connaddr(rp, nam) 160 struct rawcb *rp; 161 struct mbuf *nam; 162 { 163 struct sockaddr *addr = mtod(nam, struct sockaddr *); 164 165 bcopy((caddr_t)addr, (caddr_t)&rp->rcb_faddr, sizeof(*addr)); 166 rp->rcb_flags |= RAW_FADDR; 167 } 168