1*19948Sbloom /* raw_cb.c 6.4 85/05/04 */ 25635Sroot 317066Sbloom #include "param.h" 417066Sbloom #include "systm.h" 517066Sbloom #include "mbuf.h" 617066Sbloom #include "socket.h" 717066Sbloom #include "socketvar.h" 817066Sbloom #include "errno.h" 910890Ssam 1017066Sbloom #include "if.h" 1117066Sbloom #include "route.h" 1217066Sbloom #include "raw_cb.h" 1312783Ssam #include "../netinet/in.h" 14*19948Sbloom #ifdef PUP 1512783Ssam #include "../netpup/pup.h" 16*19948Sbloom #endif 175635Sroot 1810890Ssam #include "../vax/mtpr.h" 1910890Ssam 205635Sroot /* 215635Sroot * Routines to manage the raw protocol control blocks. 225635Sroot * 235635Sroot * TODO: 245635Sroot * hash lookups by protocol family/protocol + address family 256339Ssam * take care of unique address problems per AF? 266045Swnj * redo address binding to allow wildcards 275635Sroot */ 285635Sroot 295635Sroot /* 305635Sroot * Allocate a control block and a nominal amount 315635Sroot * of buffer space for the socket. 325635Sroot */ 338394Swnj raw_attach(so) 345635Sroot register struct socket *so; 355635Sroot { 365635Sroot struct mbuf *m; 375635Sroot register struct rawcb *rp; 385635Sroot 399638Ssam m = m_getclr(M_DONTWAIT, MT_PCB); 405635Sroot if (m == 0) 415635Sroot return (ENOBUFS); 425635Sroot if (sbreserve(&so->so_snd, RAWSNDQ) == 0) 435635Sroot goto bad; 445635Sroot if (sbreserve(&so->so_rcv, RAWRCVQ) == 0) 455635Sroot goto bad2; 465635Sroot rp = mtod(m, struct rawcb *); 475635Sroot rp->rcb_socket = so; 485635Sroot insque(rp, &rawcb); 495635Sroot so->so_pcb = (caddr_t)rp; 505635Sroot rp->rcb_pcb = 0; 515635Sroot return (0); 525635Sroot bad2: 535635Sroot sbrelease(&so->so_snd); 545635Sroot bad: 555635Sroot (void) m_free(m); 565635Sroot return (ENOBUFS); 575635Sroot } 585635Sroot 595635Sroot /* 605635Sroot * Detach the raw connection block and discard 615635Sroot * socket resources. 625635Sroot */ 635635Sroot raw_detach(rp) 645635Sroot register struct rawcb *rp; 655635Sroot { 665635Sroot struct socket *so = rp->rcb_socket; 675635Sroot 685635Sroot so->so_pcb = 0; 695635Sroot sofree(so); 705635Sroot remque(rp); 718975Sroot m_freem(dtom(rp)); 725635Sroot } 735635Sroot 745635Sroot /* 755635Sroot * Disconnect and possibly release resources. 765635Sroot */ 775635Sroot raw_disconnect(rp) 785635Sroot struct rawcb *rp; 795635Sroot { 808975Sroot 816509Ssam rp->rcb_flags &= ~RAW_FADDR; 827517Sroot if (rp->rcb_socket->so_state & SS_NOFDREF) 835635Sroot raw_detach(rp); 845635Sroot } 855635Sroot 868394Swnj raw_bind(so, nam) 878394Swnj register struct socket *so; 888394Swnj struct mbuf *nam; 898394Swnj { 908394Swnj struct sockaddr *addr = mtod(nam, struct sockaddr *); 918394Swnj register struct rawcb *rp; 928394Swnj 938394Swnj if (ifnet == 0) 948394Swnj return (EADDRNOTAVAIL); 958394Swnj /* BEGIN DUBIOUS */ 968394Swnj /* 978394Swnj * Should we verify address not already in use? 988394Swnj * Some say yes, others no. 998394Swnj */ 1008394Swnj switch (addr->sa_family) { 1018394Swnj 10212783Ssam #ifdef INET 1038394Swnj case AF_IMPLINK: 10412783Ssam case AF_INET: { 1058394Swnj if (((struct sockaddr_in *)addr)->sin_addr.s_addr && 10618409Skarels ifa_ifwithaddr(addr) == 0) 1078394Swnj return (EADDRNOTAVAIL); 1088394Swnj break; 10912783Ssam } 11012783Ssam #endif 1118394Swnj 1128394Swnj #ifdef PUP 1138394Swnj /* 1148394Swnj * Curious, we convert PUP address format to internet 1158394Swnj * to allow us to verify we're asking for an Ethernet 1168394Swnj * interface. This is wrong, but things are heavily 1178394Swnj * oriented towards the internet addressing scheme, and 1188394Swnj * converting internet to PUP would be very expensive. 1198394Swnj */ 1208394Swnj case AF_PUP: { 1218394Swnj struct sockaddr_pup *spup = (struct sockaddr_pup *)addr; 1228394Swnj struct sockaddr_in inpup; 1238394Swnj 1249184Ssam bzero((caddr_t)&inpup, (unsigned)sizeof(inpup)); 1258394Swnj inpup.sin_family = AF_INET; 12618409Skarels inpup.sin_addr = in_makeaddr(spup->spup_net, spup->spup_host); 1278394Swnj if (inpup.sin_addr.s_addr && 12818409Skarels ifa_ifwithaddr((struct sockaddr *)&inpup) == 0) 1298394Swnj return (EADDRNOTAVAIL); 1308394Swnj break; 1318394Swnj } 1328394Swnj #endif 1338394Swnj 1348394Swnj default: 1358394Swnj return (EAFNOSUPPORT); 1368394Swnj } 1378394Swnj /* END DUBIOUS */ 1389184Ssam rp = sotorawcb(so); 1398394Swnj bcopy((caddr_t)addr, (caddr_t)&rp->rcb_laddr, sizeof (*addr)); 1408394Swnj rp->rcb_flags |= RAW_LADDR; 1418394Swnj return (0); 1428394Swnj } 1438394Swnj 1445635Sroot /* 1455635Sroot * Associate a peer's address with a 1465635Sroot * raw connection block. 1475635Sroot */ 1488394Swnj raw_connaddr(rp, nam) 1495635Sroot struct rawcb *rp; 1508394Swnj struct mbuf *nam; 1515635Sroot { 1528394Swnj struct sockaddr *addr = mtod(nam, struct sockaddr *); 1538394Swnj 1546509Ssam bcopy((caddr_t)addr, (caddr_t)&rp->rcb_faddr, sizeof(*addr)); 1556509Ssam rp->rcb_flags |= RAW_FADDR; 1565635Sroot } 157