1*5772Swnj /* raw_cb.c 4.3 82/02/12 */ 25635Sroot 35635Sroot #include "../h/param.h" 45635Sroot #include "../h/systm.h" 55635Sroot #include "../h/mbuf.h" 65635Sroot #include "../h/socket.h" 75635Sroot #include "../h/socketvar.h" 85635Sroot #include "../h/mtpr.h" 95635Sroot #include "../net/in.h" 105635Sroot #include "../net/in_systm.h" 115635Sroot #include "../net/if.h" 125635Sroot #include "../net/raw_cb.h" 135635Sroot #include "/usr/include/errno.h" 145635Sroot 155635Sroot /* 165635Sroot * Routines to manage the raw protocol control blocks. 175635Sroot * 185635Sroot * TODO: 195635Sroot * hash lookups by protocol family/protocol + address family 205635Sroot * take care of unique address problems per AF 215635Sroot */ 225635Sroot 235635Sroot /* 245635Sroot * Allocate a control block and a nominal amount 255635Sroot * of buffer space for the socket. 265635Sroot */ 275635Sroot raw_attach(so, addr) 285635Sroot register struct socket *so; 295635Sroot struct sockaddr *addr; 305635Sroot { 315635Sroot struct mbuf *m; 325635Sroot register struct rawcb *rp; 335635Sroot struct ifnet *ifp = ifnet; 345635Sroot 355635Sroot COUNT(RAW_ATTACH); 365635Sroot /* 375635Sroot * Should we verify address not already in use? 385635Sroot * Some say yes, others no. 395635Sroot */ 405635Sroot if (addr) switch (addr->sa_family) { 415635Sroot 42*5772Swnj case AF_IMPLINK: 435635Sroot case AF_INET: { 445635Sroot register struct sockaddr_in *sin = (struct sockaddr_in *)addr; 455635Sroot 465635Sroot if (ifnet && sin->sin_addr.s_addr == 0) 475635Sroot sin->sin_addr = ifnet->if_addr; 485635Sroot ifp = if_ifwithaddr(sin->sin_addr); 495635Sroot break; 505635Sroot } 515635Sroot 525635Sroot default: 535635Sroot return (EAFNOSUPPORT); 545635Sroot } 555635Sroot if (ifp == 0) 565635Sroot return (EADDRNOTAVAIL); 575635Sroot m = m_getclr(M_DONTWAIT); 585635Sroot if (m == 0) 595635Sroot return (ENOBUFS); 605635Sroot if (sbreserve(&so->so_snd, RAWSNDQ) == 0) 615635Sroot goto bad; 625635Sroot if (sbreserve(&so->so_rcv, RAWRCVQ) == 0) 635635Sroot goto bad2; 645635Sroot rp = mtod(m, struct rawcb *); 655635Sroot rp->rcb_socket = so; 665635Sroot insque(rp, &rawcb); 675635Sroot so->so_pcb = (caddr_t)rp; 685635Sroot rp->rcb_pcb = 0; 695635Sroot 705635Sroot if (addr) 715635Sroot bcopy(addr, &so->so_addr, sizeof(*addr)); 725635Sroot return (0); 735635Sroot bad2: 745635Sroot sbrelease(&so->so_snd); 755635Sroot bad: 765635Sroot (void) m_free(m); 775635Sroot return (ENOBUFS); 785635Sroot } 795635Sroot 805635Sroot /* 815635Sroot * Detach the raw connection block and discard 825635Sroot * socket resources. 835635Sroot */ 845635Sroot raw_detach(rp) 855635Sroot register struct rawcb *rp; 865635Sroot { 875635Sroot struct socket *so = rp->rcb_socket; 885635Sroot 895635Sroot COUNT(RAW_DETACH); 905635Sroot so->so_pcb = 0; 915635Sroot sofree(so); 925635Sroot remque(rp); 935635Sroot (void) m_freem(dtom(rp)); 945635Sroot } 955635Sroot 965635Sroot /* 975635Sroot * Disconnect and possibly release resources. 985635Sroot */ 995635Sroot raw_disconnect(rp) 1005635Sroot struct rawcb *rp; 1015635Sroot { 1025635Sroot COUNT(RAW_DISCONNECT); 1035635Sroot rp->rcb_flags &= ~RAW_ADDR; 1045635Sroot if (rp->rcb_socket->so_state & SS_USERGONE) 1055635Sroot raw_detach(rp); 1065635Sroot } 1075635Sroot 1085635Sroot /* 1095635Sroot * Associate a peer's address with a 1105635Sroot * raw connection block. 1115635Sroot */ 1125635Sroot raw_connaddr(rp, addr) 1135635Sroot struct rawcb *rp; 1145635Sroot struct sockaddr *addr; 1155635Sroot { 1165635Sroot COUNT(RAW_CONNADDR); 1175635Sroot bcopy(addr, &rp->rcb_addr, sizeof(struct sockaddr)); 1185635Sroot rp->rcb_flags |= RAW_ADDR; 1195635Sroot } 120