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