1*21769Skarels /* raw_cb.c 6.5 85/06/02 */ 25635Sroot 317066Sbloom #include "param.h" 417066Sbloom #include "systm.h" 517066Sbloom #include "mbuf.h" 617066Sbloom #include "socket.h" 717066Sbloom #include "socketvar.h" 8*21769Skarels #include "domain.h" 9*21769Skarels #include "protosw.h" 1017066Sbloom #include "errno.h" 1110890Ssam 1217066Sbloom #include "if.h" 1317066Sbloom #include "route.h" 1417066Sbloom #include "raw_cb.h" 1512783Ssam #include "../netinet/in.h" 1619948Sbloom #ifdef PUP 1712783Ssam #include "../netpup/pup.h" 1819948Sbloom #endif 195635Sroot 2010890Ssam #include "../vax/mtpr.h" 2110890Ssam 225635Sroot /* 235635Sroot * Routines to manage the raw protocol control blocks. 245635Sroot * 255635Sroot * TODO: 265635Sroot * hash lookups by protocol family/protocol + address family 276339Ssam * take care of unique address problems per AF? 286045Swnj * redo address binding to allow wildcards 295635Sroot */ 305635Sroot 315635Sroot /* 325635Sroot * Allocate a control block and a nominal amount 335635Sroot * of buffer space for the socket. 345635Sroot */ 35*21769Skarels raw_attach(so, proto) 365635Sroot register struct socket *so; 37*21769Skarels int proto; 385635Sroot { 395635Sroot struct mbuf *m; 405635Sroot register struct rawcb *rp; 415635Sroot 429638Ssam m = m_getclr(M_DONTWAIT, MT_PCB); 435635Sroot if (m == 0) 445635Sroot return (ENOBUFS); 455635Sroot if (sbreserve(&so->so_snd, RAWSNDQ) == 0) 465635Sroot goto bad; 475635Sroot if (sbreserve(&so->so_rcv, RAWRCVQ) == 0) 485635Sroot goto bad2; 495635Sroot rp = mtod(m, struct rawcb *); 505635Sroot rp->rcb_socket = so; 515635Sroot so->so_pcb = (caddr_t)rp; 525635Sroot rp->rcb_pcb = 0; 53*21769Skarels rp->rcb_proto.sp_family = so->so_proto->pr_domain->dom_family; 54*21769Skarels rp->rcb_proto.sp_protocol = proto; 55*21769Skarels insque(rp, &rawcb); 565635Sroot return (0); 575635Sroot bad2: 585635Sroot sbrelease(&so->so_snd); 595635Sroot bad: 605635Sroot (void) m_free(m); 615635Sroot return (ENOBUFS); 625635Sroot } 635635Sroot 645635Sroot /* 655635Sroot * Detach the raw connection block and discard 665635Sroot * socket resources. 675635Sroot */ 685635Sroot raw_detach(rp) 695635Sroot register struct rawcb *rp; 705635Sroot { 715635Sroot struct socket *so = rp->rcb_socket; 725635Sroot 735635Sroot so->so_pcb = 0; 745635Sroot sofree(so); 755635Sroot remque(rp); 768975Sroot m_freem(dtom(rp)); 775635Sroot } 785635Sroot 795635Sroot /* 805635Sroot * Disconnect and possibly release resources. 815635Sroot */ 825635Sroot raw_disconnect(rp) 835635Sroot struct rawcb *rp; 845635Sroot { 858975Sroot 866509Ssam rp->rcb_flags &= ~RAW_FADDR; 877517Sroot if (rp->rcb_socket->so_state & SS_NOFDREF) 885635Sroot raw_detach(rp); 895635Sroot } 905635Sroot 918394Swnj raw_bind(so, nam) 928394Swnj register struct socket *so; 938394Swnj struct mbuf *nam; 948394Swnj { 958394Swnj struct sockaddr *addr = mtod(nam, struct sockaddr *); 968394Swnj register struct rawcb *rp; 978394Swnj 988394Swnj if (ifnet == 0) 998394Swnj return (EADDRNOTAVAIL); 1008394Swnj /* BEGIN DUBIOUS */ 1018394Swnj /* 1028394Swnj * Should we verify address not already in use? 1038394Swnj * Some say yes, others no. 1048394Swnj */ 1058394Swnj switch (addr->sa_family) { 1068394Swnj 10712783Ssam #ifdef INET 1088394Swnj case AF_IMPLINK: 10912783Ssam case AF_INET: { 1108394Swnj if (((struct sockaddr_in *)addr)->sin_addr.s_addr && 11118409Skarels ifa_ifwithaddr(addr) == 0) 1128394Swnj return (EADDRNOTAVAIL); 1138394Swnj break; 11412783Ssam } 11512783Ssam #endif 1168394Swnj 1178394Swnj #ifdef PUP 1188394Swnj /* 1198394Swnj * Curious, we convert PUP address format to internet 1208394Swnj * to allow us to verify we're asking for an Ethernet 1218394Swnj * interface. This is wrong, but things are heavily 1228394Swnj * oriented towards the internet addressing scheme, and 1238394Swnj * converting internet to PUP would be very expensive. 1248394Swnj */ 1258394Swnj case AF_PUP: { 1268394Swnj struct sockaddr_pup *spup = (struct sockaddr_pup *)addr; 1278394Swnj struct sockaddr_in inpup; 1288394Swnj 1299184Ssam bzero((caddr_t)&inpup, (unsigned)sizeof(inpup)); 1308394Swnj inpup.sin_family = AF_INET; 13118409Skarels inpup.sin_addr = in_makeaddr(spup->spup_net, spup->spup_host); 1328394Swnj if (inpup.sin_addr.s_addr && 13318409Skarels ifa_ifwithaddr((struct sockaddr *)&inpup) == 0) 1348394Swnj return (EADDRNOTAVAIL); 1358394Swnj break; 1368394Swnj } 1378394Swnj #endif 1388394Swnj 1398394Swnj default: 1408394Swnj return (EAFNOSUPPORT); 1418394Swnj } 1428394Swnj /* END DUBIOUS */ 1439184Ssam rp = sotorawcb(so); 1448394Swnj bcopy((caddr_t)addr, (caddr_t)&rp->rcb_laddr, sizeof (*addr)); 1458394Swnj rp->rcb_flags |= RAW_LADDR; 1468394Swnj return (0); 1478394Swnj } 1488394Swnj 1495635Sroot /* 1505635Sroot * Associate a peer's address with a 1515635Sroot * raw connection block. 1525635Sroot */ 1538394Swnj raw_connaddr(rp, nam) 1545635Sroot struct rawcb *rp; 1558394Swnj struct mbuf *nam; 1565635Sroot { 1578394Swnj struct sockaddr *addr = mtod(nam, struct sockaddr *); 1588394Swnj 1596509Ssam bcopy((caddr_t)addr, (caddr_t)&rp->rcb_faddr, sizeof(*addr)); 1606509Ssam rp->rcb_flags |= RAW_FADDR; 1615635Sroot } 162