123160Smckusick /* 223160Smckusick * Copyright (c) 1980 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*24774Skarels * @(#)raw_cb.c 6.7 (Berkeley) 09/16/85 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" 2219948Sbloom #ifdef PUP 2312783Ssam #include "../netpup/pup.h" 2419948Sbloom #endif 255635Sroot 2610890Ssam #include "../vax/mtpr.h" 2710890Ssam 285635Sroot /* 295635Sroot * Routines to manage the raw protocol control blocks. 305635Sroot * 315635Sroot * TODO: 325635Sroot * hash lookups by protocol family/protocol + address family 336339Ssam * take care of unique address problems per AF? 346045Swnj * redo address binding to allow wildcards 355635Sroot */ 365635Sroot 375635Sroot /* 385635Sroot * Allocate a control block and a nominal amount 395635Sroot * of buffer space for the socket. 405635Sroot */ 4121769Skarels raw_attach(so, proto) 425635Sroot register struct socket *so; 4321769Skarels int proto; 445635Sroot { 455635Sroot struct mbuf *m; 465635Sroot register struct rawcb *rp; 475635Sroot 489638Ssam m = m_getclr(M_DONTWAIT, MT_PCB); 495635Sroot if (m == 0) 505635Sroot return (ENOBUFS); 515635Sroot if (sbreserve(&so->so_snd, RAWSNDQ) == 0) 525635Sroot goto bad; 535635Sroot if (sbreserve(&so->so_rcv, RAWRCVQ) == 0) 545635Sroot goto bad2; 555635Sroot rp = mtod(m, struct rawcb *); 565635Sroot rp->rcb_socket = so; 575635Sroot so->so_pcb = (caddr_t)rp; 585635Sroot rp->rcb_pcb = 0; 5921769Skarels rp->rcb_proto.sp_family = so->so_proto->pr_domain->dom_family; 6021769Skarels rp->rcb_proto.sp_protocol = proto; 6121769Skarels insque(rp, &rawcb); 625635Sroot return (0); 635635Sroot bad2: 645635Sroot sbrelease(&so->so_snd); 655635Sroot bad: 665635Sroot (void) m_free(m); 675635Sroot return (ENOBUFS); 685635Sroot } 695635Sroot 705635Sroot /* 715635Sroot * Detach the raw connection block and discard 725635Sroot * socket resources. 735635Sroot */ 745635Sroot raw_detach(rp) 755635Sroot register struct rawcb *rp; 765635Sroot { 775635Sroot struct socket *so = rp->rcb_socket; 785635Sroot 79*24774Skarels if (rp->rcb_route.ro_rt) 80*24774Skarels rtfree(rp->rcb_route.ro_rt); 815635Sroot so->so_pcb = 0; 825635Sroot sofree(so); 835635Sroot remque(rp); 848975Sroot m_freem(dtom(rp)); 855635Sroot } 865635Sroot 875635Sroot /* 885635Sroot * Disconnect and possibly release resources. 895635Sroot */ 905635Sroot raw_disconnect(rp) 915635Sroot struct rawcb *rp; 925635Sroot { 938975Sroot 946509Ssam rp->rcb_flags &= ~RAW_FADDR; 957517Sroot if (rp->rcb_socket->so_state & SS_NOFDREF) 965635Sroot raw_detach(rp); 975635Sroot } 985635Sroot 998394Swnj raw_bind(so, nam) 1008394Swnj register struct socket *so; 1018394Swnj struct mbuf *nam; 1028394Swnj { 1038394Swnj struct sockaddr *addr = mtod(nam, struct sockaddr *); 1048394Swnj register struct rawcb *rp; 1058394Swnj 1068394Swnj if (ifnet == 0) 1078394Swnj return (EADDRNOTAVAIL); 1088394Swnj /* BEGIN DUBIOUS */ 1098394Swnj /* 1108394Swnj * Should we verify address not already in use? 1118394Swnj * Some say yes, others no. 1128394Swnj */ 1138394Swnj switch (addr->sa_family) { 1148394Swnj 115*24774Skarels #if defined(INET) || defined(BBNNET) 1168394Swnj case AF_IMPLINK: 11712783Ssam case AF_INET: { 1188394Swnj if (((struct sockaddr_in *)addr)->sin_addr.s_addr && 11918409Skarels ifa_ifwithaddr(addr) == 0) 1208394Swnj return (EADDRNOTAVAIL); 1218394Swnj break; 12212783Ssam } 12312783Ssam #endif 1248394Swnj 1258394Swnj #ifdef PUP 1268394Swnj /* 1278394Swnj * Curious, we convert PUP address format to internet 1288394Swnj * to allow us to verify we're asking for an Ethernet 1298394Swnj * interface. This is wrong, but things are heavily 1308394Swnj * oriented towards the internet addressing scheme, and 1318394Swnj * converting internet to PUP would be very expensive. 1328394Swnj */ 1338394Swnj case AF_PUP: { 1348394Swnj struct sockaddr_pup *spup = (struct sockaddr_pup *)addr; 1358394Swnj struct sockaddr_in inpup; 1368394Swnj 1379184Ssam bzero((caddr_t)&inpup, (unsigned)sizeof(inpup)); 1388394Swnj inpup.sin_family = AF_INET; 13918409Skarels inpup.sin_addr = in_makeaddr(spup->spup_net, spup->spup_host); 1408394Swnj if (inpup.sin_addr.s_addr && 14118409Skarels ifa_ifwithaddr((struct sockaddr *)&inpup) == 0) 1428394Swnj return (EADDRNOTAVAIL); 1438394Swnj break; 1448394Swnj } 1458394Swnj #endif 1468394Swnj 1478394Swnj default: 1488394Swnj return (EAFNOSUPPORT); 1498394Swnj } 1508394Swnj /* END DUBIOUS */ 1519184Ssam rp = sotorawcb(so); 1528394Swnj bcopy((caddr_t)addr, (caddr_t)&rp->rcb_laddr, sizeof (*addr)); 1538394Swnj rp->rcb_flags |= RAW_LADDR; 1548394Swnj return (0); 1558394Swnj } 1568394Swnj 1575635Sroot /* 1585635Sroot * Associate a peer's address with a 1595635Sroot * raw connection block. 1605635Sroot */ 1618394Swnj raw_connaddr(rp, nam) 1625635Sroot struct rawcb *rp; 1638394Swnj struct mbuf *nam; 1645635Sroot { 1658394Swnj struct sockaddr *addr = mtod(nam, struct sockaddr *); 1668394Swnj 1676509Ssam bcopy((caddr_t)addr, (caddr_t)&rp->rcb_faddr, sizeof(*addr)); 1686509Ssam rp->rcb_flags |= RAW_FADDR; 1695635Sroot } 170