1: /* 2: * Copyright (c) 1980, 1986 Regents of the University of California. 3: * All rights reserved. 4: * 5: * Redistribution and use in source and binary forms are permitted 6: * provided that this notice is preserved and that due credit is given 7: * to the University of California at Berkeley. The name of the University 8: * may not be used to endorse or promote products derived from this 9: * software without specific prior written permission. This software 10: * is provided ``as is'' without express or implied warranty. 11: * 12: * @(#)raw_cb.c 7.4 (Berkeley) 12/30/87 13: */ 14: 15: #include "param.h" 16: #include "systm.h" 17: #include "mbuf.h" 18: #include "socket.h" 19: #include "socketvar.h" 20: #include "domain.h" 21: #include "protosw.h" 22: #include "errno.h" 23: 24: #include "if.h" 25: #include "route.h" 26: #include "raw_cb.h" 27: #include "../netinet/in.h" 28: 29: /* 30: * Routines to manage the raw protocol control blocks. 31: * 32: * TODO: 33: * hash lookups by protocol family/protocol + address family 34: * take care of unique address problems per AF? 35: * redo address binding to allow wildcards 36: */ 37: 38: /* 39: * Allocate a control block and a nominal amount 40: * of buffer space for the socket. 41: */ 42: raw_attach(so, proto) 43: register struct socket *so; 44: int proto; 45: { 46: struct mbuf *m; 47: register struct rawcb *rp; 48: 49: m = m_getclr(M_DONTWAIT, MT_PCB); 50: if (m == 0) 51: return (ENOBUFS); 52: if (sbreserve(&so->so_snd, RAWSNDQ) == 0) 53: goto bad; 54: if (sbreserve(&so->so_rcv, RAWRCVQ) == 0) 55: goto bad2; 56: rp = mtod(m, struct rawcb *); 57: rp->rcb_socket = so; 58: so->so_pcb = (caddr_t)rp; 59: rp->rcb_pcb = 0; 60: rp->rcb_proto.sp_family = so->so_proto->pr_domain->dom_family; 61: rp->rcb_proto.sp_protocol = proto; 62: insque(rp, &rawcb); 63: return (0); 64: bad2: 65: sbrelease(&so->so_snd); 66: bad: 67: (void) m_free(m); 68: return (ENOBUFS); 69: } 70: 71: /* 72: * Detach the raw connection block and discard 73: * socket resources. 74: */ 75: raw_detach(rp) 76: register struct rawcb *rp; 77: { 78: struct socket *so = rp->rcb_socket; 79: 80: if (rp->rcb_route.ro_rt) 81: rtfree(rp->rcb_route.ro_rt); 82: so->so_pcb = 0; 83: sofree(so); 84: remque(rp); 85: if (rp->rcb_options) 86: m_freem(rp->rcb_options); 87: m_freem(dtom(rp)); 88: } 89: 90: /* 91: * Disconnect and possibly release resources. 92: */ 93: raw_disconnect(rp) 94: struct rawcb *rp; 95: { 96: 97: rp->rcb_flags &= ~RAW_FADDR; 98: if (rp->rcb_socket->so_state & SS_NOFDREF) 99: raw_detach(rp); 100: } 101: 102: raw_bind(so, nam) 103: register struct socket *so; 104: struct mbuf *nam; 105: { 106: struct sockaddr *addr = mtod(nam, struct sockaddr *); 107: register struct rawcb *rp; 108: 109: if (ifnet == 0) 110: return (EADDRNOTAVAIL); 111: /* BEGIN DUBIOUS */ 112: /* 113: * Should we verify address not already in use? 114: * Some say yes, others no. 115: */ 116: switch (addr->sa_family) { 117: 118: #ifdef INET 119: case AF_IMPLINK: 120: case AF_INET: { 121: if (((struct sockaddr_in *)addr)->sin_addr.s_addr && 122: ifa_ifwithaddr(addr) == 0) 123: return (EADDRNOTAVAIL); 124: break; 125: } 126: #endif 127: 128: default: 129: return (EAFNOSUPPORT); 130: } 131: /* END DUBIOUS */ 132: rp = sotorawcb(so); 133: bcopy((caddr_t)addr, (caddr_t)&rp->rcb_laddr, sizeof (*addr)); 134: rp->rcb_flags |= RAW_LADDR; 135: return (0); 136: } 137: 138: /* 139: * Associate a peer's address with a 140: * raw connection block. 141: */ 142: raw_connaddr(rp, nam) 143: struct rawcb *rp; 144: struct mbuf *nam; 145: { 146: struct sockaddr *addr = mtod(nam, struct sockaddr *); 147: 148: bcopy((caddr_t)addr, (caddr_t)&rp->rcb_faddr, sizeof(*addr)); 149: rp->rcb_flags |= RAW_FADDR; 150: }