1*6529Ssam /* raw_cb.c 4.8 82/04/11 */ 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" 136339Ssam #include "../net/pup.h" 146045Swnj #include "../errno.h" 155635Sroot 165635Sroot /* 175635Sroot * Routines to manage the raw protocol control blocks. 185635Sroot * 195635Sroot * TODO: 205635Sroot * hash lookups by protocol family/protocol + address family 216339Ssam * take care of unique address problems per AF? 226045Swnj * redo address binding to allow wildcards 235635Sroot */ 245635Sroot 255635Sroot /* 265635Sroot * Allocate a control block and a nominal amount 275635Sroot * of buffer space for the socket. 285635Sroot */ 295635Sroot raw_attach(so, addr) 305635Sroot register struct socket *so; 315635Sroot struct sockaddr *addr; 325635Sroot { 335635Sroot struct mbuf *m; 345635Sroot register struct rawcb *rp; 355635Sroot 365635Sroot COUNT(RAW_ATTACH); 376339Ssam if (ifnet == 0) 386339Ssam return (EADDRNOTAVAIL); 395635Sroot /* 405635Sroot * Should we verify address not already in use? 415635Sroot * Some say yes, others no. 425635Sroot */ 435635Sroot if (addr) switch (addr->sa_family) { 445635Sroot 455772Swnj case AF_IMPLINK: 466339Ssam case AF_INET: 476339Ssam if (((struct sockaddr_in *)addr)->sin_addr.s_addr && 486339Ssam if_ifwithaddr(addr) == 0) 496339Ssam return (EADDRNOTAVAIL); 505635Sroot break; 515635Sroot 526339Ssam #ifdef PUP 536339Ssam /* 546339Ssam * Curious, we convert PUP address format to internet 556339Ssam * to allow us to verify we're asking for an Ethernet 566339Ssam * interface. This is wrong, but things are heavily 576339Ssam * oriented towards the internet addressing scheme, and 586339Ssam * converting internet to PUP would be very expensive. 596339Ssam */ 606339Ssam case AF_PUP: { 616339Ssam struct sockaddr_pup *spup = (struct sockaddr_pup *)addr; 626339Ssam struct sockaddr_in inpup; 636339Ssam 646339Ssam bzero((caddr_t)&inpup, sizeof(inpup)); 656509Ssam inpup.sin_family = AF_INET; 666339Ssam inpup.sin_addr.s_net = spup->sp_net; 676339Ssam inpup.sin_addr.s_impno = spup->sp_host; 686339Ssam if (inpup.sin_addr.s_addr && 696339Ssam if_ifwithaddr((struct sockaddr *)&inpup) == 0) 706339Ssam return (EADDRNOTAVAIL); 716045Swnj break; 726339Ssam } 736339Ssam #endif 746045Swnj 755635Sroot default: 765635Sroot return (EAFNOSUPPORT); 775635Sroot } 785635Sroot m = m_getclr(M_DONTWAIT); 795635Sroot if (m == 0) 805635Sroot return (ENOBUFS); 815635Sroot if (sbreserve(&so->so_snd, RAWSNDQ) == 0) 825635Sroot goto bad; 835635Sroot if (sbreserve(&so->so_rcv, RAWRCVQ) == 0) 845635Sroot goto bad2; 855635Sroot rp = mtod(m, struct rawcb *); 865635Sroot rp->rcb_socket = so; 875635Sroot insque(rp, &rawcb); 885635Sroot so->so_pcb = (caddr_t)rp; 895635Sroot rp->rcb_pcb = 0; 90*6529Ssam if (addr) { 916509Ssam bcopy((caddr_t)addr, (caddr_t)&rp->rcb_laddr, sizeof(*addr)); 92*6529Ssam rp->rcb_flags |= RAW_LADDR; 93*6529Ssam } 945635Sroot return (0); 955635Sroot bad2: 965635Sroot sbrelease(&so->so_snd); 975635Sroot bad: 985635Sroot (void) m_free(m); 995635Sroot return (ENOBUFS); 1005635Sroot } 1015635Sroot 1025635Sroot /* 1035635Sroot * Detach the raw connection block and discard 1045635Sroot * socket resources. 1055635Sroot */ 1065635Sroot raw_detach(rp) 1075635Sroot register struct rawcb *rp; 1085635Sroot { 1095635Sroot struct socket *so = rp->rcb_socket; 1105635Sroot 1115635Sroot COUNT(RAW_DETACH); 1125635Sroot so->so_pcb = 0; 1135635Sroot sofree(so); 1145635Sroot remque(rp); 1156339Ssam (void) m_freem(dtom(rp)); 1165635Sroot } 1175635Sroot 1185635Sroot /* 1195635Sroot * Disconnect and possibly release resources. 1205635Sroot */ 1215635Sroot raw_disconnect(rp) 1225635Sroot struct rawcb *rp; 1235635Sroot { 1245635Sroot COUNT(RAW_DISCONNECT); 1256509Ssam rp->rcb_flags &= ~RAW_FADDR; 1265635Sroot if (rp->rcb_socket->so_state & SS_USERGONE) 1275635Sroot raw_detach(rp); 1285635Sroot } 1295635Sroot 1305635Sroot /* 1315635Sroot * Associate a peer's address with a 1325635Sroot * raw connection block. 1335635Sroot */ 1345635Sroot raw_connaddr(rp, addr) 1355635Sroot struct rawcb *rp; 1365635Sroot struct sockaddr *addr; 1375635Sroot { 1385635Sroot COUNT(RAW_CONNADDR); 1396509Ssam bcopy((caddr_t)addr, (caddr_t)&rp->rcb_faddr, sizeof(*addr)); 1406509Ssam rp->rcb_flags |= RAW_FADDR; 1415635Sroot } 142