1*17066Sbloom /* raw_cb.c 6.2 84/08/29 */ 25635Sroot 3*17066Sbloom #include "param.h" 4*17066Sbloom #include "systm.h" 5*17066Sbloom #include "mbuf.h" 6*17066Sbloom #include "socket.h" 7*17066Sbloom #include "socketvar.h" 8*17066Sbloom #include "errno.h" 910890Ssam 10*17066Sbloom #include "if.h" 11*17066Sbloom #include "route.h" 12*17066Sbloom #include "raw_cb.h" 1312783Ssam #include "../netinet/in.h" 1412783Ssam #include "../netpup/pup.h" 155635Sroot 1610890Ssam #include "../vax/mtpr.h" 1710890Ssam 185635Sroot /* 195635Sroot * Routines to manage the raw protocol control blocks. 205635Sroot * 215635Sroot * TODO: 225635Sroot * hash lookups by protocol family/protocol + address family 236339Ssam * take care of unique address problems per AF? 246045Swnj * redo address binding to allow wildcards 255635Sroot */ 265635Sroot 275635Sroot /* 285635Sroot * Allocate a control block and a nominal amount 295635Sroot * of buffer space for the socket. 305635Sroot */ 318394Swnj raw_attach(so) 325635Sroot register struct socket *so; 335635Sroot { 345635Sroot struct mbuf *m; 355635Sroot register struct rawcb *rp; 365635Sroot 379638Ssam m = m_getclr(M_DONTWAIT, MT_PCB); 385635Sroot if (m == 0) 395635Sroot return (ENOBUFS); 405635Sroot if (sbreserve(&so->so_snd, RAWSNDQ) == 0) 415635Sroot goto bad; 425635Sroot if (sbreserve(&so->so_rcv, RAWRCVQ) == 0) 435635Sroot goto bad2; 445635Sroot rp = mtod(m, struct rawcb *); 455635Sroot rp->rcb_socket = so; 465635Sroot insque(rp, &rawcb); 475635Sroot so->so_pcb = (caddr_t)rp; 485635Sroot rp->rcb_pcb = 0; 495635Sroot return (0); 505635Sroot bad2: 515635Sroot sbrelease(&so->so_snd); 525635Sroot bad: 535635Sroot (void) m_free(m); 545635Sroot return (ENOBUFS); 555635Sroot } 565635Sroot 575635Sroot /* 585635Sroot * Detach the raw connection block and discard 595635Sroot * socket resources. 605635Sroot */ 615635Sroot raw_detach(rp) 625635Sroot register struct rawcb *rp; 635635Sroot { 645635Sroot struct socket *so = rp->rcb_socket; 655635Sroot 665635Sroot so->so_pcb = 0; 675635Sroot sofree(so); 685635Sroot remque(rp); 698975Sroot m_freem(dtom(rp)); 705635Sroot } 715635Sroot 725635Sroot /* 735635Sroot * Disconnect and possibly release resources. 745635Sroot */ 755635Sroot raw_disconnect(rp) 765635Sroot struct rawcb *rp; 775635Sroot { 788975Sroot 796509Ssam rp->rcb_flags &= ~RAW_FADDR; 807517Sroot if (rp->rcb_socket->so_state & SS_NOFDREF) 815635Sroot raw_detach(rp); 825635Sroot } 835635Sroot 848394Swnj raw_bind(so, nam) 858394Swnj register struct socket *so; 868394Swnj struct mbuf *nam; 878394Swnj { 888394Swnj struct sockaddr *addr = mtod(nam, struct sockaddr *); 898394Swnj register struct rawcb *rp; 908394Swnj 918394Swnj if (ifnet == 0) 928394Swnj return (EADDRNOTAVAIL); 938394Swnj /* BEGIN DUBIOUS */ 948394Swnj /* 958394Swnj * Should we verify address not already in use? 968394Swnj * Some say yes, others no. 978394Swnj */ 988394Swnj switch (addr->sa_family) { 998394Swnj 10012783Ssam #ifdef INET 1018394Swnj case AF_IMPLINK: 10212783Ssam case AF_INET: { 1038394Swnj if (((struct sockaddr_in *)addr)->sin_addr.s_addr && 1048394Swnj if_ifwithaddr(addr) == 0) 1058394Swnj return (EADDRNOTAVAIL); 1068394Swnj break; 10712783Ssam } 10812783Ssam #endif 1098394Swnj 1108394Swnj #ifdef PUP 1118394Swnj /* 1128394Swnj * Curious, we convert PUP address format to internet 1138394Swnj * to allow us to verify we're asking for an Ethernet 1148394Swnj * interface. This is wrong, but things are heavily 1158394Swnj * oriented towards the internet addressing scheme, and 1168394Swnj * converting internet to PUP would be very expensive. 1178394Swnj */ 1188394Swnj case AF_PUP: { 1198394Swnj struct sockaddr_pup *spup = (struct sockaddr_pup *)addr; 1208394Swnj struct sockaddr_in inpup; 1218394Swnj 1229184Ssam bzero((caddr_t)&inpup, (unsigned)sizeof(inpup)); 1238394Swnj inpup.sin_family = AF_INET; 12413220Ssam inpup.sin_addr = if_makeaddr(spup->spup_net, spup->spup_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