1*6161Ssam /* raw_cb.c 4.5 82/03/13 */ 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" 136045Swnj #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 216045Swnj * redo address binding to allow wildcards 225635Sroot */ 235635Sroot 245635Sroot /* 255635Sroot * Allocate a control block and a nominal amount 265635Sroot * of buffer space for the socket. 275635Sroot */ 285635Sroot raw_attach(so, addr) 295635Sroot register struct socket *so; 305635Sroot struct sockaddr *addr; 315635Sroot { 325635Sroot struct mbuf *m; 335635Sroot register struct rawcb *rp; 345635Sroot struct ifnet *ifp = ifnet; 355635Sroot 365635Sroot COUNT(RAW_ATTACH); 375635Sroot /* 385635Sroot * Should we verify address not already in use? 395635Sroot * Some say yes, others no. 405635Sroot */ 415635Sroot if (addr) switch (addr->sa_family) { 425635Sroot 435772Swnj case AF_IMPLINK: 445635Sroot case AF_INET: { 455635Sroot register struct sockaddr_in *sin = (struct sockaddr_in *)addr; 465635Sroot 475635Sroot if (ifnet && sin->sin_addr.s_addr == 0) 485635Sroot sin->sin_addr = ifnet->if_addr; 495635Sroot ifp = if_ifwithaddr(sin->sin_addr); 505635Sroot break; 515635Sroot } 525635Sroot 536045Swnj case AF_PUP: 546045Swnj ifp = ifnet; 556045Swnj break; 566045Swnj 575635Sroot default: 585635Sroot return (EAFNOSUPPORT); 595635Sroot } 605635Sroot if (ifp == 0) 615635Sroot return (EADDRNOTAVAIL); 625635Sroot m = m_getclr(M_DONTWAIT); 635635Sroot if (m == 0) 645635Sroot return (ENOBUFS); 655635Sroot if (sbreserve(&so->so_snd, RAWSNDQ) == 0) 665635Sroot goto bad; 675635Sroot if (sbreserve(&so->so_rcv, RAWRCVQ) == 0) 685635Sroot goto bad2; 695635Sroot rp = mtod(m, struct rawcb *); 705635Sroot rp->rcb_socket = so; 715635Sroot insque(rp, &rawcb); 725635Sroot so->so_pcb = (caddr_t)rp; 735635Sroot rp->rcb_pcb = 0; 745635Sroot 755635Sroot if (addr) 76*6161Ssam bcopy((caddr_t)addr, (caddr_t)&so->so_addr, sizeof(*addr)); 775635Sroot return (0); 785635Sroot bad2: 795635Sroot sbrelease(&so->so_snd); 805635Sroot bad: 815635Sroot (void) m_free(m); 825635Sroot return (ENOBUFS); 835635Sroot } 845635Sroot 855635Sroot /* 865635Sroot * Detach the raw connection block and discard 875635Sroot * socket resources. 885635Sroot */ 895635Sroot raw_detach(rp) 905635Sroot register struct rawcb *rp; 915635Sroot { 925635Sroot struct socket *so = rp->rcb_socket; 935635Sroot 945635Sroot COUNT(RAW_DETACH); 955635Sroot so->so_pcb = 0; 965635Sroot sofree(so); 975635Sroot remque(rp); 98*6161Ssam m_freem(dtom(rp)); 995635Sroot } 1005635Sroot 1015635Sroot /* 1025635Sroot * Disconnect and possibly release resources. 1035635Sroot */ 1045635Sroot raw_disconnect(rp) 1055635Sroot struct rawcb *rp; 1065635Sroot { 1075635Sroot COUNT(RAW_DISCONNECT); 1085635Sroot rp->rcb_flags &= ~RAW_ADDR; 1095635Sroot if (rp->rcb_socket->so_state & SS_USERGONE) 1105635Sroot raw_detach(rp); 1115635Sroot } 1125635Sroot 1135635Sroot /* 1145635Sroot * Associate a peer's address with a 1155635Sroot * raw connection block. 1165635Sroot */ 1175635Sroot raw_connaddr(rp, addr) 1185635Sroot struct rawcb *rp; 1195635Sroot struct sockaddr *addr; 1205635Sroot { 1215635Sroot COUNT(RAW_CONNADDR); 122*6161Ssam bcopy((caddr_t)addr, (caddr_t)&rp->rcb_addr, sizeof(struct sockaddr)); 1235635Sroot rp->rcb_flags |= RAW_ADDR; 1245635Sroot } 125