ddp_usrreq.c revision 165974
1/*- 2 * Copyright (c) 2004-2005 Robert N. M. Watson 3 * 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 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * Copyright (c) 1990, 1994 Regents of The University of Michigan. 27 * All Rights Reserved. 28 * 29 * Permission to use, copy, modify, and distribute this software and 30 * its documentation for any purpose and without fee is hereby granted, 31 * provided that the above copyright notice appears in all copies and 32 * that both that copyright notice and this permission notice appear 33 * in supporting documentation, and that the name of The University 34 * of Michigan not be used in advertising or publicity pertaining to 35 * distribution of the software without specific, written prior 36 * permission. This software is supplied as is without expressed or 37 * implied warranties of any kind. 38 * 39 * This product includes software developed by the University of 40 * California, Berkeley and its contributors. 41 * 42 * Research Systems Unix Group 43 * The University of Michigan 44 * c/o Wesley Craig 45 * 535 W. William Street 46 * Ann Arbor, Michigan 47 * +1-313-764-2278 48 * netatalk@umich.edu 49 * 50 * $FreeBSD: head/sys/netatalk/ddp_usrreq.c 165974 2007-01-12 15:07:51Z rwatson $ 51 */ 52 53#include <sys/param.h> 54#include <sys/systm.h> 55#include <sys/malloc.h> 56#include <sys/mbuf.h> 57#include <sys/socket.h> 58#include <sys/socketvar.h> 59#include <sys/protosw.h> 60#include <net/if.h> 61#include <net/route.h> 62#include <net/netisr.h> 63 64#include <netatalk/at.h> 65#include <netatalk/at_var.h> 66#include <netatalk/ddp_var.h> 67#include <netatalk/ddp_pcb.h> 68#include <netatalk/at_extern.h> 69 70static u_long ddp_sendspace = DDP_MAXSZ; /* Max ddp size + 1 (ddp_type) */ 71static u_long ddp_recvspace = 10 * (587 + sizeof(struct sockaddr_at)); 72 73static struct ifqueue atintrq1, atintrq2, aarpintrq; 74 75static int 76ddp_attach(struct socket *so, int proto, struct thread *td) 77{ 78 struct ddpcb *ddp; 79 int error = 0; 80 81 ddp = sotoddpcb(so); 82 KASSERT(ddp == NULL, ("ddp_attach: ddp != NULL")); 83 84 /* 85 * Allocate socket buffer space first so that it's present 86 * before first use. 87 */ 88 error = soreserve(so, ddp_sendspace, ddp_recvspace); 89 if (error) 90 return (error); 91 92 DDP_LIST_XLOCK(); 93 error = at_pcballoc(so); 94 DDP_LIST_XUNLOCK(); 95 return (error); 96} 97 98static void 99ddp_detach(struct socket *so) 100{ 101 struct ddpcb *ddp; 102 103 ddp = sotoddpcb(so); 104 KASSERT(ddp != NULL, ("ddp_detach: ddp == NULL")); 105 106 DDP_LIST_XLOCK(); 107 DDP_LOCK(ddp); 108 at_pcbdetach(so, ddp); 109 DDP_LIST_XUNLOCK(); 110} 111 112static int 113ddp_bind(struct socket *so, struct sockaddr *nam, struct thread *td) 114{ 115 struct ddpcb *ddp; 116 int error = 0; 117 118 ddp = sotoddpcb(so); 119 KASSERT(ddp != NULL, ("ddp_bind: ddp == NULL")); 120 121 DDP_LIST_XLOCK(); 122 DDP_LOCK(ddp); 123 error = at_pcbsetaddr(ddp, nam, td); 124 DDP_UNLOCK(ddp); 125 DDP_LIST_XUNLOCK(); 126 return (error); 127} 128 129static int 130ddp_connect(struct socket *so, struct sockaddr *nam, struct thread *td) 131{ 132 struct ddpcb *ddp; 133 int error = 0; 134 135 ddp = sotoddpcb(so); 136 KASSERT(ddp != NULL, ("ddp_connect: ddp == NULL")); 137 138 DDP_LIST_XLOCK(); 139 DDP_LOCK(ddp); 140 if (ddp->ddp_fsat.sat_port != ATADDR_ANYPORT) { 141 DDP_UNLOCK(ddp); 142 DDP_LIST_XUNLOCK(); 143 return (EISCONN); 144 } 145 146 error = at_pcbconnect( ddp, nam, td ); 147 DDP_UNLOCK(ddp); 148 DDP_LIST_XUNLOCK(); 149 if (error == 0) 150 soisconnected(so); 151 return (error); 152} 153 154static int 155ddp_disconnect(struct socket *so) 156{ 157 struct ddpcb *ddp; 158 159 ddp = sotoddpcb(so); 160 KASSERT(ddp != NULL, ("ddp_disconnect: ddp == NULL")); 161 162 DDP_LOCK(ddp); 163 if (ddp->ddp_fsat.sat_addr.s_node == ATADDR_ANYNODE) { 164 DDP_UNLOCK(ddp); 165 return (ENOTCONN); 166 } 167 168 at_pcbdisconnect(ddp); 169 ddp->ddp_fsat.sat_addr.s_node = ATADDR_ANYNODE; 170 DDP_UNLOCK(ddp); 171 soisdisconnected(so); 172 return (0); 173} 174 175static int 176ddp_shutdown(struct socket *so) 177{ 178 struct ddpcb *ddp; 179 180 ddp = sotoddpcb(so); 181 KASSERT(ddp != NULL, ("ddp_shutdown: ddp == NULL")); 182 183 socantsendmore(so); 184 return (0); 185} 186 187static int 188ddp_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr, 189 struct mbuf *control, struct thread *td) 190{ 191 struct ddpcb *ddp; 192 int error = 0; 193 194 ddp = sotoddpcb(so); 195 KASSERT(ddp != NULL, ("ddp_send: ddp == NULL")); 196 197 if (control && control->m_len) 198 return (EINVAL); 199 200 if (addr != NULL) { 201 DDP_LIST_XLOCK(); 202 DDP_LOCK(ddp); 203 if (ddp->ddp_fsat.sat_port != ATADDR_ANYPORT) { 204 error = EISCONN; 205 goto out; 206 } 207 208 error = at_pcbconnect(ddp, addr, td); 209 if (error == 0) { 210 error = ddp_output(m, so); 211 at_pcbdisconnect(ddp); 212 } 213out: 214 DDP_UNLOCK(ddp); 215 DDP_LIST_XUNLOCK(); 216 } else { 217 DDP_LOCK(ddp); 218 if (ddp->ddp_fsat.sat_port == ATADDR_ANYPORT) 219 error = ENOTCONN; 220 else 221 error = ddp_output(m, so); 222 DDP_UNLOCK(ddp); 223 } 224 return (error); 225} 226 227/* 228 * XXXRW: This is never called because we only invoke abort on stream 229 * protocols. 230 */ 231static void 232ddp_abort(struct socket *so) 233{ 234 struct ddpcb *ddp; 235 236 ddp = sotoddpcb(so); 237 KASSERT(ddp != NULL, ("ddp_abort: ddp == NULL")); 238 239 DDP_LOCK(ddp); 240 at_pcbdisconnect(ddp); 241 DDP_UNLOCK(ddp); 242 soisdisconnected(so); 243} 244 245static void 246ddp_close(struct socket *so) 247{ 248 struct ddpcb *ddp; 249 250 ddp = sotoddpcb(so); 251 KASSERT(ddp != NULL, ("ddp_close: ddp == NULL")); 252 253 DDP_LOCK(ddp); 254 at_pcbdisconnect(ddp); 255 DDP_UNLOCK(ddp); 256 soisdisconnected(so); 257} 258 259void 260ddp_init(void) 261{ 262 263 atintrq1.ifq_maxlen = IFQ_MAXLEN; 264 atintrq2.ifq_maxlen = IFQ_MAXLEN; 265 aarpintrq.ifq_maxlen = IFQ_MAXLEN; 266 mtx_init(&atintrq1.ifq_mtx, "at1_inq", NULL, MTX_DEF); 267 mtx_init(&atintrq2.ifq_mtx, "at2_inq", NULL, MTX_DEF); 268 mtx_init(&aarpintrq.ifq_mtx, "aarp_inq", NULL, MTX_DEF); 269 DDP_LIST_LOCK_INIT(); 270 netisr_register(NETISR_ATALK1, at1intr, &atintrq1, NETISR_MPSAFE); 271 netisr_register(NETISR_ATALK2, at2intr, &atintrq2, NETISR_MPSAFE); 272 netisr_register(NETISR_AARP, aarpintr, &aarpintrq, NETISR_MPSAFE); 273} 274 275#if 0 276static void 277ddp_clean(void) 278{ 279 struct ddpcp *ddp; 280 281 for (ddp = ddpcb_list; ddp != NULL; ddp = ddp->ddp_next) 282 at_pcbdetach(ddp->ddp_socket, ddp); 283 DDP_LIST_LOCK_DESTROY(); 284} 285#endif 286 287static int 288at_setpeeraddr(struct socket *so, struct sockaddr **nam) 289{ 290 291 return (EOPNOTSUPP); 292} 293 294static int 295at_setsockaddr(struct socket *so, struct sockaddr **nam) 296{ 297 struct ddpcb *ddp; 298 299 ddp = sotoddpcb(so); 300 KASSERT(ddp != NULL, ("at_setsockaddr: ddp == NULL")); 301 302 DDP_LOCK(ddp); 303 at_sockaddr(ddp, nam); 304 DDP_UNLOCK(ddp); 305 return (0); 306} 307 308struct pr_usrreqs ddp_usrreqs = { 309 .pru_abort = ddp_abort, 310 .pru_attach = ddp_attach, 311 .pru_bind = ddp_bind, 312 .pru_connect = ddp_connect, 313 .pru_control = at_control, 314 .pru_detach = ddp_detach, 315 .pru_disconnect = ddp_disconnect, 316 .pru_peeraddr = at_setpeeraddr, 317 .pru_send = ddp_send, 318 .pru_shutdown = ddp_shutdown, 319 .pru_sockaddr = at_setsockaddr, 320 .pru_close = ddp_close, 321}; 322