123160Smckusick /* 229066Smckusick * Copyright (c) 1980, 1986 Regents of the University of California. 323160Smckusick * All rights reserved. The Berkeley software License Agreement 423160Smckusick * specifies the terms and conditions for redistribution. 523160Smckusick * 6*29922Skarels * @(#)raw_cb.c 7.3 (Berkeley) 10/28/86 723160Smckusick */ 85635Sroot 917066Sbloom #include "param.h" 1017066Sbloom #include "systm.h" 1117066Sbloom #include "mbuf.h" 1217066Sbloom #include "socket.h" 1317066Sbloom #include "socketvar.h" 1421769Skarels #include "domain.h" 1521769Skarels #include "protosw.h" 1617066Sbloom #include "errno.h" 1710890Ssam 1817066Sbloom #include "if.h" 1917066Sbloom #include "route.h" 2017066Sbloom #include "raw_cb.h" 2112783Ssam #include "../netinet/in.h" 225635Sroot 23*29922Skarels #include "../machine/mtpr.h" 2410890Ssam 255635Sroot /* 265635Sroot * Routines to manage the raw protocol control blocks. 275635Sroot * 285635Sroot * TODO: 295635Sroot * hash lookups by protocol family/protocol + address family 306339Ssam * take care of unique address problems per AF? 316045Swnj * redo address binding to allow wildcards 325635Sroot */ 335635Sroot 345635Sroot /* 355635Sroot * Allocate a control block and a nominal amount 365635Sroot * of buffer space for the socket. 375635Sroot */ 3821769Skarels raw_attach(so, proto) 395635Sroot register struct socket *so; 4021769Skarels int proto; 415635Sroot { 425635Sroot struct mbuf *m; 435635Sroot register struct rawcb *rp; 445635Sroot 459638Ssam m = m_getclr(M_DONTWAIT, MT_PCB); 465635Sroot if (m == 0) 475635Sroot return (ENOBUFS); 485635Sroot if (sbreserve(&so->so_snd, RAWSNDQ) == 0) 495635Sroot goto bad; 505635Sroot if (sbreserve(&so->so_rcv, RAWRCVQ) == 0) 515635Sroot goto bad2; 525635Sroot rp = mtod(m, struct rawcb *); 535635Sroot rp->rcb_socket = so; 545635Sroot so->so_pcb = (caddr_t)rp; 555635Sroot rp->rcb_pcb = 0; 5621769Skarels rp->rcb_proto.sp_family = so->so_proto->pr_domain->dom_family; 5721769Skarels rp->rcb_proto.sp_protocol = proto; 5821769Skarels insque(rp, &rawcb); 595635Sroot return (0); 605635Sroot bad2: 615635Sroot sbrelease(&so->so_snd); 625635Sroot bad: 635635Sroot (void) m_free(m); 645635Sroot return (ENOBUFS); 655635Sroot } 665635Sroot 675635Sroot /* 685635Sroot * Detach the raw connection block and discard 695635Sroot * socket resources. 705635Sroot */ 715635Sroot raw_detach(rp) 725635Sroot register struct rawcb *rp; 735635Sroot { 745635Sroot struct socket *so = rp->rcb_socket; 755635Sroot 7624774Skarels if (rp->rcb_route.ro_rt) 7724774Skarels rtfree(rp->rcb_route.ro_rt); 785635Sroot so->so_pcb = 0; 795635Sroot sofree(so); 805635Sroot remque(rp); 8126035Skarels if (rp->rcb_options) 8229569Skarels m_freem(rp->rcb_options); 838975Sroot m_freem(dtom(rp)); 845635Sroot } 855635Sroot 865635Sroot /* 875635Sroot * Disconnect and possibly release resources. 885635Sroot */ 895635Sroot raw_disconnect(rp) 905635Sroot struct rawcb *rp; 915635Sroot { 928975Sroot 936509Ssam rp->rcb_flags &= ~RAW_FADDR; 947517Sroot if (rp->rcb_socket->so_state & SS_NOFDREF) 955635Sroot raw_detach(rp); 965635Sroot } 975635Sroot 988394Swnj raw_bind(so, nam) 998394Swnj register struct socket *so; 1008394Swnj struct mbuf *nam; 1018394Swnj { 1028394Swnj struct sockaddr *addr = mtod(nam, struct sockaddr *); 1038394Swnj register struct rawcb *rp; 1048394Swnj 1058394Swnj if (ifnet == 0) 1068394Swnj return (EADDRNOTAVAIL); 1078394Swnj /* BEGIN DUBIOUS */ 1088394Swnj /* 1098394Swnj * Should we verify address not already in use? 1108394Swnj * Some say yes, others no. 1118394Swnj */ 1128394Swnj switch (addr->sa_family) { 1138394Swnj 11425647Skarels #ifdef INET 1158394Swnj case AF_IMPLINK: 11612783Ssam case AF_INET: { 1178394Swnj if (((struct sockaddr_in *)addr)->sin_addr.s_addr && 11818409Skarels ifa_ifwithaddr(addr) == 0) 1198394Swnj return (EADDRNOTAVAIL); 1208394Swnj break; 12112783Ssam } 12212783Ssam #endif 1238394Swnj 1248394Swnj default: 1258394Swnj return (EAFNOSUPPORT); 1268394Swnj } 1278394Swnj /* END DUBIOUS */ 1289184Ssam rp = sotorawcb(so); 1298394Swnj bcopy((caddr_t)addr, (caddr_t)&rp->rcb_laddr, sizeof (*addr)); 1308394Swnj rp->rcb_flags |= RAW_LADDR; 1318394Swnj return (0); 1328394Swnj } 1338394Swnj 1345635Sroot /* 1355635Sroot * Associate a peer's address with a 1365635Sroot * raw connection block. 1375635Sroot */ 1388394Swnj raw_connaddr(rp, nam) 1395635Sroot struct rawcb *rp; 1408394Swnj struct mbuf *nam; 1415635Sroot { 1428394Swnj struct sockaddr *addr = mtod(nam, struct sockaddr *); 1438394Swnj 1446509Ssam bcopy((caddr_t)addr, (caddr_t)&rp->rcb_faddr, sizeof(*addr)); 1456509Ssam rp->rcb_flags |= RAW_FADDR; 1465635Sroot } 147