123160Smckusick /* 229066Smckusick * Copyright (c) 1980, 1986 Regents of the University of California. 3*33183Sbostic * All rights reserved. 423160Smckusick * 5*33183Sbostic * Redistribution and use in source and binary forms are permitted 6*33183Sbostic * provided that this notice is preserved and that due credit is given 7*33183Sbostic * to the University of California at Berkeley. The name of the University 8*33183Sbostic * may not be used to endorse or promote products derived from this 9*33183Sbostic * software without specific prior written permission. This software 10*33183Sbostic * is provided ``as is'' without express or implied warranty. 11*33183Sbostic * 12*33183Sbostic * @(#)raw_cb.c 7.4 (Berkeley) 12/30/87 1323160Smckusick */ 145635Sroot 1517066Sbloom #include "param.h" 1617066Sbloom #include "systm.h" 1717066Sbloom #include "mbuf.h" 1817066Sbloom #include "socket.h" 1917066Sbloom #include "socketvar.h" 2021769Skarels #include "domain.h" 2121769Skarels #include "protosw.h" 2217066Sbloom #include "errno.h" 2310890Ssam 2417066Sbloom #include "if.h" 2517066Sbloom #include "route.h" 2617066Sbloom #include "raw_cb.h" 2712783Ssam #include "../netinet/in.h" 285635Sroot 2929922Skarels #include "../machine/mtpr.h" 3010890Ssam 315635Sroot /* 325635Sroot * Routines to manage the raw protocol control blocks. 335635Sroot * 345635Sroot * TODO: 355635Sroot * hash lookups by protocol family/protocol + address family 366339Ssam * take care of unique address problems per AF? 376045Swnj * redo address binding to allow wildcards 385635Sroot */ 395635Sroot 405635Sroot /* 415635Sroot * Allocate a control block and a nominal amount 425635Sroot * of buffer space for the socket. 435635Sroot */ 4421769Skarels raw_attach(so, proto) 455635Sroot register struct socket *so; 4621769Skarels int proto; 475635Sroot { 485635Sroot struct mbuf *m; 495635Sroot register struct rawcb *rp; 505635Sroot 519638Ssam m = m_getclr(M_DONTWAIT, MT_PCB); 525635Sroot if (m == 0) 535635Sroot return (ENOBUFS); 545635Sroot if (sbreserve(&so->so_snd, RAWSNDQ) == 0) 555635Sroot goto bad; 565635Sroot if (sbreserve(&so->so_rcv, RAWRCVQ) == 0) 575635Sroot goto bad2; 585635Sroot rp = mtod(m, struct rawcb *); 595635Sroot rp->rcb_socket = so; 605635Sroot so->so_pcb = (caddr_t)rp; 615635Sroot rp->rcb_pcb = 0; 6221769Skarels rp->rcb_proto.sp_family = so->so_proto->pr_domain->dom_family; 6321769Skarels rp->rcb_proto.sp_protocol = proto; 6421769Skarels insque(rp, &rawcb); 655635Sroot return (0); 665635Sroot bad2: 675635Sroot sbrelease(&so->so_snd); 685635Sroot bad: 695635Sroot (void) m_free(m); 705635Sroot return (ENOBUFS); 715635Sroot } 725635Sroot 735635Sroot /* 745635Sroot * Detach the raw connection block and discard 755635Sroot * socket resources. 765635Sroot */ 775635Sroot raw_detach(rp) 785635Sroot register struct rawcb *rp; 795635Sroot { 805635Sroot struct socket *so = rp->rcb_socket; 815635Sroot 8224774Skarels if (rp->rcb_route.ro_rt) 8324774Skarels rtfree(rp->rcb_route.ro_rt); 845635Sroot so->so_pcb = 0; 855635Sroot sofree(so); 865635Sroot remque(rp); 8726035Skarels if (rp->rcb_options) 8829569Skarels m_freem(rp->rcb_options); 898975Sroot m_freem(dtom(rp)); 905635Sroot } 915635Sroot 925635Sroot /* 935635Sroot * Disconnect and possibly release resources. 945635Sroot */ 955635Sroot raw_disconnect(rp) 965635Sroot struct rawcb *rp; 975635Sroot { 988975Sroot 996509Ssam rp->rcb_flags &= ~RAW_FADDR; 1007517Sroot if (rp->rcb_socket->so_state & SS_NOFDREF) 1015635Sroot raw_detach(rp); 1025635Sroot } 1035635Sroot 1048394Swnj raw_bind(so, nam) 1058394Swnj register struct socket *so; 1068394Swnj struct mbuf *nam; 1078394Swnj { 1088394Swnj struct sockaddr *addr = mtod(nam, struct sockaddr *); 1098394Swnj register struct rawcb *rp; 1108394Swnj 1118394Swnj if (ifnet == 0) 1128394Swnj return (EADDRNOTAVAIL); 1138394Swnj /* BEGIN DUBIOUS */ 1148394Swnj /* 1158394Swnj * Should we verify address not already in use? 1168394Swnj * Some say yes, others no. 1178394Swnj */ 1188394Swnj switch (addr->sa_family) { 1198394Swnj 12025647Skarels #ifdef INET 1218394Swnj case AF_IMPLINK: 12212783Ssam case AF_INET: { 1238394Swnj if (((struct sockaddr_in *)addr)->sin_addr.s_addr && 12418409Skarels ifa_ifwithaddr(addr) == 0) 1258394Swnj return (EADDRNOTAVAIL); 1268394Swnj break; 12712783Ssam } 12812783Ssam #endif 1298394Swnj 1308394Swnj default: 1318394Swnj return (EAFNOSUPPORT); 1328394Swnj } 1338394Swnj /* END DUBIOUS */ 1349184Ssam rp = sotorawcb(so); 1358394Swnj bcopy((caddr_t)addr, (caddr_t)&rp->rcb_laddr, sizeof (*addr)); 1368394Swnj rp->rcb_flags |= RAW_LADDR; 1378394Swnj return (0); 1388394Swnj } 1398394Swnj 1405635Sroot /* 1415635Sroot * Associate a peer's address with a 1425635Sroot * raw connection block. 1435635Sroot */ 1448394Swnj raw_connaddr(rp, nam) 1455635Sroot struct rawcb *rp; 1468394Swnj struct mbuf *nam; 1475635Sroot { 1488394Swnj struct sockaddr *addr = mtod(nam, struct sockaddr *); 1498394Swnj 1506509Ssam bcopy((caddr_t)addr, (caddr_t)&rp->rcb_faddr, sizeof(*addr)); 1516509Ssam rp->rcb_flags |= RAW_FADDR; 1525635Sroot } 153