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