123160Smckusick /* 229066Smckusick * Copyright (c) 1980, 1986 Regents of the University of California. 333183Sbostic * All rights reserved. 423160Smckusick * 533183Sbostic * Redistribution and use in source and binary forms are permitted 6*34844Sbostic * provided that the above copyright notice and this paragraph are 7*34844Sbostic * duplicated in all such forms and that any documentation, 8*34844Sbostic * advertising materials, and other materials related to such 9*34844Sbostic * distribution and use acknowledge that the software was developed 10*34844Sbostic * by the University of California, Berkeley. The name of the 11*34844Sbostic * University may not be used to endorse or promote products derived 12*34844Sbostic * from this software without specific prior written permission. 13*34844Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14*34844Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15*34844Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1633183Sbostic * 17*34844Sbostic * @(#)raw_cb.c 7.6 (Berkeley) 06/27/88 1823160Smckusick */ 195635Sroot 2017066Sbloom #include "param.h" 2117066Sbloom #include "systm.h" 2217066Sbloom #include "mbuf.h" 2317066Sbloom #include "socket.h" 2417066Sbloom #include "socketvar.h" 2521769Skarels #include "domain.h" 2621769Skarels #include "protosw.h" 2717066Sbloom #include "errno.h" 2810890Ssam 2917066Sbloom #include "if.h" 3017066Sbloom #include "route.h" 3117066Sbloom #include "raw_cb.h" 3212783Ssam #include "../netinet/in.h" 335635Sroot 3429922Skarels #include "../machine/mtpr.h" 3510890Ssam 365635Sroot /* 375635Sroot * Routines to manage the raw protocol control blocks. 385635Sroot * 395635Sroot * TODO: 405635Sroot * hash lookups by protocol family/protocol + address family 416339Ssam * take care of unique address problems per AF? 426045Swnj * redo address binding to allow wildcards 435635Sroot */ 445635Sroot 455635Sroot /* 465635Sroot * Allocate a control block and a nominal amount 475635Sroot * of buffer space for the socket. 485635Sroot */ 4921769Skarels raw_attach(so, proto) 505635Sroot register struct socket *so; 5121769Skarels int proto; 525635Sroot { 535635Sroot struct mbuf *m; 545635Sroot register struct rawcb *rp; 555635Sroot 569638Ssam m = m_getclr(M_DONTWAIT, MT_PCB); 575635Sroot if (m == 0) 585635Sroot return (ENOBUFS); 5934554Skarels if (sbreserve(&so->so_snd, (u_long) RAWSNDQ) == 0) 605635Sroot goto bad; 6134554Skarels if (sbreserve(&so->so_rcv, (u_long) RAWRCVQ) == 0) 625635Sroot goto bad2; 635635Sroot rp = mtod(m, struct rawcb *); 645635Sroot rp->rcb_socket = so; 655635Sroot so->so_pcb = (caddr_t)rp; 665635Sroot rp->rcb_pcb = 0; 6721769Skarels rp->rcb_proto.sp_family = so->so_proto->pr_domain->dom_family; 6821769Skarels rp->rcb_proto.sp_protocol = proto; 6921769Skarels insque(rp, &rawcb); 705635Sroot return (0); 715635Sroot bad2: 725635Sroot sbrelease(&so->so_snd); 735635Sroot bad: 745635Sroot (void) m_free(m); 755635Sroot return (ENOBUFS); 765635Sroot } 775635Sroot 785635Sroot /* 795635Sroot * Detach the raw connection block and discard 805635Sroot * socket resources. 815635Sroot */ 825635Sroot raw_detach(rp) 835635Sroot register struct rawcb *rp; 845635Sroot { 855635Sroot struct socket *so = rp->rcb_socket; 865635Sroot 8724774Skarels if (rp->rcb_route.ro_rt) 8824774Skarels rtfree(rp->rcb_route.ro_rt); 895635Sroot so->so_pcb = 0; 905635Sroot sofree(so); 915635Sroot remque(rp); 9226035Skarels if (rp->rcb_options) 9329569Skarels m_freem(rp->rcb_options); 948975Sroot m_freem(dtom(rp)); 955635Sroot } 965635Sroot 975635Sroot /* 985635Sroot * Disconnect and possibly release resources. 995635Sroot */ 1005635Sroot raw_disconnect(rp) 1015635Sroot struct rawcb *rp; 1025635Sroot { 1038975Sroot 1046509Ssam rp->rcb_flags &= ~RAW_FADDR; 1057517Sroot if (rp->rcb_socket->so_state & SS_NOFDREF) 1065635Sroot raw_detach(rp); 1075635Sroot } 1085635Sroot 1098394Swnj raw_bind(so, nam) 1108394Swnj register struct socket *so; 1118394Swnj struct mbuf *nam; 1128394Swnj { 1138394Swnj struct sockaddr *addr = mtod(nam, struct sockaddr *); 1148394Swnj register struct rawcb *rp; 1158394Swnj 1168394Swnj if (ifnet == 0) 1178394Swnj return (EADDRNOTAVAIL); 1188394Swnj /* BEGIN DUBIOUS */ 1198394Swnj /* 1208394Swnj * Should we verify address not already in use? 1218394Swnj * Some say yes, others no. 1228394Swnj */ 1238394Swnj switch (addr->sa_family) { 1248394Swnj 12525647Skarels #ifdef INET 1268394Swnj case AF_IMPLINK: 12712783Ssam case AF_INET: { 1288394Swnj if (((struct sockaddr_in *)addr)->sin_addr.s_addr && 12918409Skarels ifa_ifwithaddr(addr) == 0) 1308394Swnj return (EADDRNOTAVAIL); 1318394Swnj break; 13212783Ssam } 13312783Ssam #endif 1348394Swnj 1358394Swnj default: 1368394Swnj return (EAFNOSUPPORT); 1378394Swnj } 1388394Swnj /* END DUBIOUS */ 1399184Ssam rp = sotorawcb(so); 1408394Swnj bcopy((caddr_t)addr, (caddr_t)&rp->rcb_laddr, sizeof (*addr)); 1418394Swnj rp->rcb_flags |= RAW_LADDR; 1428394Swnj return (0); 1438394Swnj } 1448394Swnj 1455635Sroot /* 1465635Sroot * Associate a peer's address with a 1475635Sroot * raw connection block. 1485635Sroot */ 1498394Swnj raw_connaddr(rp, nam) 1505635Sroot struct rawcb *rp; 1518394Swnj struct mbuf *nam; 1525635Sroot { 1538394Swnj struct sockaddr *addr = mtod(nam, struct sockaddr *); 1548394Swnj 1556509Ssam bcopy((caddr_t)addr, (caddr_t)&rp->rcb_faddr, sizeof(*addr)); 1566509Ssam rp->rcb_flags |= RAW_FADDR; 1575635Sroot } 158