raw_usrreq.c revision 67893
1/* 2 * Copyright (c) 1980, 1986, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#)raw_usrreq.c 8.1 (Berkeley) 6/10/93 34 * $FreeBSD: head/sys/net/raw_usrreq.c 67893 2000-10-29 16:06:56Z phk $ 35 */ 36 37#include <sys/param.h> 38#include <sys/systm.h> 39#include <sys/mbuf.h> 40#include <sys/protosw.h> 41#include <sys/socket.h> 42#include <sys/socketvar.h> 43 44#include <net/raw_cb.h> 45 46/* 47 * Initialize raw connection block q. 48 */ 49void 50raw_init() 51{ 52 LIST_INIT(&rawcb_list); 53} 54 55 56/* 57 * Raw protocol input routine. Find the socket 58 * associated with the packet(s) and move them over. If 59 * nothing exists for this packet, drop it. 60 */ 61/* 62 * Raw protocol interface. 63 */ 64void 65raw_input(m0, proto, src, dst) 66 struct mbuf *m0; 67 register struct sockproto *proto; 68 struct sockaddr *src, *dst; 69{ 70 register struct rawcb *rp; 71 register struct mbuf *m = m0; 72 register int sockets = 0; 73 struct socket *last; 74 75 last = 0; 76 LIST_FOREACH(rp, &rawcb_list, list) { 77 if (rp->rcb_proto.sp_family != proto->sp_family) 78 continue; 79 if (rp->rcb_proto.sp_protocol && 80 rp->rcb_proto.sp_protocol != proto->sp_protocol) 81 continue; 82 /* 83 * We assume the lower level routines have 84 * placed the address in a canonical format 85 * suitable for a structure comparison. 86 * 87 * Note that if the lengths are not the same 88 * the comparison will fail at the first byte. 89 */ 90#define equal(a1, a2) \ 91 (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0) 92 if (rp->rcb_laddr && !equal(rp->rcb_laddr, dst)) 93 continue; 94 if (rp->rcb_faddr && !equal(rp->rcb_faddr, src)) 95 continue; 96 if (last) { 97 struct mbuf *n; 98 n = m_copy(m, 0, (int)M_COPYALL); 99 if (n) { 100 if (sbappendaddr(&last->so_rcv, src, 101 n, (struct mbuf *)0) == 0) 102 /* should notify about lost packet */ 103 m_freem(n); 104 else { 105 sorwakeup(last); 106 sockets++; 107 } 108 } 109 } 110 last = rp->rcb_socket; 111 } 112 if (last) { 113 if (sbappendaddr(&last->so_rcv, src, 114 m, (struct mbuf *)0) == 0) 115 m_freem(m); 116 else { 117 sorwakeup(last); 118 sockets++; 119 } 120 } else 121 m_freem(m); 122} 123 124/*ARGSUSED*/ 125void 126raw_ctlinput(cmd, arg, dummy) 127 int cmd; 128 struct sockaddr *arg; 129 void *dummy; 130{ 131 132 if (cmd < 0 || cmd > PRC_NCMDS) 133 return; 134 /* INCOMPLETE */ 135} 136 137static int 138raw_uabort(struct socket *so) 139{ 140 struct rawcb *rp = sotorawcb(so); 141 142 if (rp == 0) 143 return EINVAL; 144 raw_disconnect(rp); 145 sofree(so); 146 soisdisconnected(so); 147 return 0; 148} 149 150/* pru_accept is EOPNOTSUPP */ 151 152static int 153raw_uattach(struct socket *so, int proto, struct proc *p) 154{ 155 struct rawcb *rp = sotorawcb(so); 156 int error; 157 158 if (rp == 0) 159 return EINVAL; 160 if (p && (error = suser(p)) != 0) 161 return error; 162 return raw_attach(so, proto); 163} 164 165static int 166raw_ubind(struct socket *so, struct sockaddr *nam, struct proc *p) 167{ 168 return EINVAL; 169} 170 171static int 172raw_uconnect(struct socket *so, struct sockaddr *nam, struct proc *p) 173{ 174 return EINVAL; 175} 176 177/* pru_connect2 is EOPNOTSUPP */ 178/* pru_control is EOPNOTSUPP */ 179 180static int 181raw_udetach(struct socket *so) 182{ 183 struct rawcb *rp = sotorawcb(so); 184 185 if (rp == 0) 186 return EINVAL; 187 188 raw_detach(rp); 189 return 0; 190} 191 192static int 193raw_udisconnect(struct socket *so) 194{ 195 struct rawcb *rp = sotorawcb(so); 196 197 if (rp == 0) 198 return EINVAL; 199 if (rp->rcb_faddr == 0) { 200 return ENOTCONN; 201 } 202 raw_disconnect(rp); 203 soisdisconnected(so); 204 return 0; 205} 206 207/* pru_listen is EOPNOTSUPP */ 208 209static int 210raw_upeeraddr(struct socket *so, struct sockaddr **nam) 211{ 212 struct rawcb *rp = sotorawcb(so); 213 214 if (rp == 0) 215 return EINVAL; 216 if (rp->rcb_faddr == 0) { 217 return ENOTCONN; 218 } 219 *nam = dup_sockaddr(rp->rcb_faddr, 1); 220 return 0; 221} 222 223/* pru_rcvd is EOPNOTSUPP */ 224/* pru_rcvoob is EOPNOTSUPP */ 225 226static int 227raw_usend(struct socket *so, int flags, struct mbuf *m, 228 struct sockaddr *nam, struct mbuf *control, struct proc *p) 229{ 230 int error; 231 struct rawcb *rp = sotorawcb(so); 232 233 if (rp == 0) { 234 error = EINVAL; 235 goto release; 236 } 237 238 if (flags & PRUS_OOB) { 239 error = EOPNOTSUPP; 240 goto release; 241 } 242 243 if (control && control->m_len) { 244 error = EOPNOTSUPP; 245 goto release; 246 } 247 if (nam) { 248 if (rp->rcb_faddr) { 249 error = EISCONN; 250 goto release; 251 } 252 rp->rcb_faddr = nam; 253 } else if (rp->rcb_faddr == 0) { 254 error = ENOTCONN; 255 goto release; 256 } 257 error = (*so->so_proto->pr_output)(m, so); 258 m = NULL; 259 if (nam) 260 rp->rcb_faddr = 0; 261release: 262 if (m != NULL) 263 m_freem(m); 264 return (error); 265} 266 267/* pru_sense is null */ 268 269static int 270raw_ushutdown(struct socket *so) 271{ 272 struct rawcb *rp = sotorawcb(so); 273 274 if (rp == 0) 275 return EINVAL; 276 socantsendmore(so); 277 return 0; 278} 279 280static int 281raw_usockaddr(struct socket *so, struct sockaddr **nam) 282{ 283 struct rawcb *rp = sotorawcb(so); 284 285 if (rp == 0) 286 return EINVAL; 287 if (rp->rcb_laddr == 0) 288 return EINVAL; 289 *nam = dup_sockaddr(rp->rcb_laddr, 1); 290 return 0; 291} 292 293struct pr_usrreqs raw_usrreqs = { 294 raw_uabort, pru_accept_notsupp, raw_uattach, raw_ubind, raw_uconnect, 295 pru_connect2_notsupp, pru_control_notsupp, raw_udetach, 296 raw_udisconnect, pru_listen_notsupp, raw_upeeraddr, pru_rcvd_notsupp, 297 pru_rcvoob_notsupp, raw_usend, pru_sense_null, raw_ushutdown, 298 raw_usockaddr, sosend, soreceive, sopoll 299}; 300