1*12783Ssam /* raw_cb.c 4.17 83/05/27 */ 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" 810890Ssam #include "../h/errno.h" 910890Ssam 105635Sroot #include "../net/if.h" 115635Sroot #include "../net/raw_cb.h" 12*12783Ssam #include "../netinet/in.h" 13*12783Ssam #include "../netpup/pup.h" 145635Sroot 1510890Ssam #include "../vax/mtpr.h" 1610890Ssam 175635Sroot /* 185635Sroot * Routines to manage the raw protocol control blocks. 195635Sroot * 205635Sroot * TODO: 215635Sroot * hash lookups by protocol family/protocol + address family 226339Ssam * take care of unique address problems per AF? 236045Swnj * redo address binding to allow wildcards 245635Sroot */ 255635Sroot 265635Sroot /* 275635Sroot * Allocate a control block and a nominal amount 285635Sroot * of buffer space for the socket. 295635Sroot */ 308394Swnj raw_attach(so) 315635Sroot register struct socket *so; 325635Sroot { 335635Sroot struct mbuf *m; 345635Sroot register struct rawcb *rp; 355635Sroot 369638Ssam m = m_getclr(M_DONTWAIT, MT_PCB); 375635Sroot if (m == 0) 385635Sroot return (ENOBUFS); 395635Sroot if (sbreserve(&so->so_snd, RAWSNDQ) == 0) 405635Sroot goto bad; 415635Sroot if (sbreserve(&so->so_rcv, RAWRCVQ) == 0) 425635Sroot goto bad2; 435635Sroot rp = mtod(m, struct rawcb *); 445635Sroot rp->rcb_socket = so; 455635Sroot insque(rp, &rawcb); 465635Sroot so->so_pcb = (caddr_t)rp; 475635Sroot rp->rcb_pcb = 0; 485635Sroot return (0); 495635Sroot bad2: 505635Sroot sbrelease(&so->so_snd); 515635Sroot bad: 525635Sroot (void) m_free(m); 535635Sroot return (ENOBUFS); 545635Sroot } 555635Sroot 565635Sroot /* 575635Sroot * Detach the raw connection block and discard 585635Sroot * socket resources. 595635Sroot */ 605635Sroot raw_detach(rp) 615635Sroot register struct rawcb *rp; 625635Sroot { 635635Sroot struct socket *so = rp->rcb_socket; 645635Sroot 655635Sroot so->so_pcb = 0; 665635Sroot sofree(so); 675635Sroot remque(rp); 688975Sroot m_freem(dtom(rp)); 695635Sroot } 705635Sroot 715635Sroot /* 725635Sroot * Disconnect and possibly release resources. 735635Sroot */ 745635Sroot raw_disconnect(rp) 755635Sroot struct rawcb *rp; 765635Sroot { 778975Sroot 786509Ssam rp->rcb_flags &= ~RAW_FADDR; 797517Sroot if (rp->rcb_socket->so_state & SS_NOFDREF) 805635Sroot raw_detach(rp); 815635Sroot } 825635Sroot 838394Swnj raw_bind(so, nam) 848394Swnj register struct socket *so; 858394Swnj struct mbuf *nam; 868394Swnj { 878394Swnj struct sockaddr *addr = mtod(nam, struct sockaddr *); 888394Swnj register struct rawcb *rp; 898394Swnj 908394Swnj if (ifnet == 0) 918394Swnj return (EADDRNOTAVAIL); 928394Swnj /* BEGIN DUBIOUS */ 938394Swnj /* 948394Swnj * Should we verify address not already in use? 958394Swnj * Some say yes, others no. 968394Swnj */ 978394Swnj switch (addr->sa_family) { 988394Swnj 99*12783Ssam #ifdef INET 1008394Swnj case AF_IMPLINK: 101*12783Ssam case AF_INET: { 1028394Swnj if (((struct sockaddr_in *)addr)->sin_addr.s_addr && 1038394Swnj if_ifwithaddr(addr) == 0) 1048394Swnj return (EADDRNOTAVAIL); 1058394Swnj break; 106*12783Ssam } 107*12783Ssam #endif 1088394Swnj 1098394Swnj #ifdef PUP 1108394Swnj /* 1118394Swnj * Curious, we convert PUP address format to internet 1128394Swnj * to allow us to verify we're asking for an Ethernet 1138394Swnj * interface. This is wrong, but things are heavily 1148394Swnj * oriented towards the internet addressing scheme, and 1158394Swnj * converting internet to PUP would be very expensive. 1168394Swnj */ 1178394Swnj case AF_PUP: { 1188394Swnj struct sockaddr_pup *spup = (struct sockaddr_pup *)addr; 1198394Swnj struct sockaddr_in inpup; 1208394Swnj 1219184Ssam bzero((caddr_t)&inpup, (unsigned)sizeof(inpup)); 1228394Swnj inpup.sin_family = AF_INET; 1238394Swnj inpup.sin_addr.s_net = spup->sp_net; 1248394Swnj inpup.sin_addr.s_impno = spup->sp_host; 1258394Swnj if (inpup.sin_addr.s_addr && 1268394Swnj if_ifwithaddr((struct sockaddr *)&inpup) == 0) 1278394Swnj return (EADDRNOTAVAIL); 1288394Swnj break; 1298394Swnj } 1308394Swnj #endif 1318394Swnj 1328394Swnj default: 1338394Swnj return (EAFNOSUPPORT); 1348394Swnj } 1358394Swnj /* END DUBIOUS */ 1369184Ssam rp = sotorawcb(so); 1378394Swnj bcopy((caddr_t)addr, (caddr_t)&rp->rcb_laddr, sizeof (*addr)); 1388394Swnj rp->rcb_flags |= RAW_LADDR; 1398394Swnj return (0); 1408394Swnj } 1418394Swnj 1425635Sroot /* 1435635Sroot * Associate a peer's address with a 1445635Sroot * raw connection block. 1455635Sroot */ 1468394Swnj raw_connaddr(rp, nam) 1475635Sroot struct rawcb *rp; 1488394Swnj struct mbuf *nam; 1495635Sroot { 1508394Swnj struct sockaddr *addr = mtod(nam, struct sockaddr *); 1518394Swnj 1526509Ssam bcopy((caddr_t)addr, (caddr_t)&rp->rcb_faddr, sizeof(*addr)); 1536509Ssam rp->rcb_flags |= RAW_FADDR; 1545635Sroot } 155