1 /* raw_cb.c 6.5 85/06/02 */ 2 3 #include "param.h" 4 #include "systm.h" 5 #include "mbuf.h" 6 #include "socket.h" 7 #include "socketvar.h" 8 #include "domain.h" 9 #include "protosw.h" 10 #include "errno.h" 11 12 #include "if.h" 13 #include "route.h" 14 #include "raw_cb.h" 15 #include "../netinet/in.h" 16 #ifdef PUP 17 #include "../netpup/pup.h" 18 #endif 19 20 #include "../vax/mtpr.h" 21 22 /* 23 * Routines to manage the raw protocol control blocks. 24 * 25 * TODO: 26 * hash lookups by protocol family/protocol + address family 27 * take care of unique address problems per AF? 28 * redo address binding to allow wildcards 29 */ 30 31 /* 32 * Allocate a control block and a nominal amount 33 * of buffer space for the socket. 34 */ 35 raw_attach(so, proto) 36 register struct socket *so; 37 int proto; 38 { 39 struct mbuf *m; 40 register struct rawcb *rp; 41 42 m = m_getclr(M_DONTWAIT, MT_PCB); 43 if (m == 0) 44 return (ENOBUFS); 45 if (sbreserve(&so->so_snd, RAWSNDQ) == 0) 46 goto bad; 47 if (sbreserve(&so->so_rcv, RAWRCVQ) == 0) 48 goto bad2; 49 rp = mtod(m, struct rawcb *); 50 rp->rcb_socket = so; 51 so->so_pcb = (caddr_t)rp; 52 rp->rcb_pcb = 0; 53 rp->rcb_proto.sp_family = so->so_proto->pr_domain->dom_family; 54 rp->rcb_proto.sp_protocol = proto; 55 insque(rp, &rawcb); 56 return (0); 57 bad2: 58 sbrelease(&so->so_snd); 59 bad: 60 (void) m_free(m); 61 return (ENOBUFS); 62 } 63 64 /* 65 * Detach the raw connection block and discard 66 * socket resources. 67 */ 68 raw_detach(rp) 69 register struct rawcb *rp; 70 { 71 struct socket *so = rp->rcb_socket; 72 73 so->so_pcb = 0; 74 sofree(so); 75 remque(rp); 76 m_freem(dtom(rp)); 77 } 78 79 /* 80 * Disconnect and possibly release resources. 81 */ 82 raw_disconnect(rp) 83 struct rawcb *rp; 84 { 85 86 rp->rcb_flags &= ~RAW_FADDR; 87 if (rp->rcb_socket->so_state & SS_NOFDREF) 88 raw_detach(rp); 89 } 90 91 raw_bind(so, nam) 92 register struct socket *so; 93 struct mbuf *nam; 94 { 95 struct sockaddr *addr = mtod(nam, struct sockaddr *); 96 register struct rawcb *rp; 97 98 if (ifnet == 0) 99 return (EADDRNOTAVAIL); 100 /* BEGIN DUBIOUS */ 101 /* 102 * Should we verify address not already in use? 103 * Some say yes, others no. 104 */ 105 switch (addr->sa_family) { 106 107 #ifdef INET 108 case AF_IMPLINK: 109 case AF_INET: { 110 if (((struct sockaddr_in *)addr)->sin_addr.s_addr && 111 ifa_ifwithaddr(addr) == 0) 112 return (EADDRNOTAVAIL); 113 break; 114 } 115 #endif 116 117 #ifdef PUP 118 /* 119 * Curious, we convert PUP address format to internet 120 * to allow us to verify we're asking for an Ethernet 121 * interface. This is wrong, but things are heavily 122 * oriented towards the internet addressing scheme, and 123 * converting internet to PUP would be very expensive. 124 */ 125 case AF_PUP: { 126 struct sockaddr_pup *spup = (struct sockaddr_pup *)addr; 127 struct sockaddr_in inpup; 128 129 bzero((caddr_t)&inpup, (unsigned)sizeof(inpup)); 130 inpup.sin_family = AF_INET; 131 inpup.sin_addr = in_makeaddr(spup->spup_net, spup->spup_host); 132 if (inpup.sin_addr.s_addr && 133 ifa_ifwithaddr((struct sockaddr *)&inpup) == 0) 134 return (EADDRNOTAVAIL); 135 break; 136 } 137 #endif 138 139 default: 140 return (EAFNOSUPPORT); 141 } 142 /* END DUBIOUS */ 143 rp = sotorawcb(so); 144 bcopy((caddr_t)addr, (caddr_t)&rp->rcb_laddr, sizeof (*addr)); 145 rp->rcb_flags |= RAW_LADDR; 146 return (0); 147 } 148 149 /* 150 * Associate a peer's address with a 151 * raw connection block. 152 */ 153 raw_connaddr(rp, nam) 154 struct rawcb *rp; 155 struct mbuf *nam; 156 { 157 struct sockaddr *addr = mtod(nam, struct sockaddr *); 158 159 bcopy((caddr_t)addr, (caddr_t)&rp->rcb_faddr, sizeof(*addr)); 160 rp->rcb_flags |= RAW_FADDR; 161 } 162