ddp_usrreq.c revision 165891
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 165891 2007-01-08 17:58:27Z 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 158 struct ddpcb *ddp; 159 160 ddp = sotoddpcb(so); 161 KASSERT(ddp != NULL, ("ddp_disconnect: ddp == NULL")); 162 163 DDP_LOCK(ddp); 164 if (ddp->ddp_fsat.sat_addr.s_node == ATADDR_ANYNODE) { 165 DDP_UNLOCK(ddp); 166 return (ENOTCONN); 167 } 168 169 at_pcbdisconnect(ddp); 170 ddp->ddp_fsat.sat_addr.s_node = ATADDR_ANYNODE; 171 DDP_UNLOCK(ddp); 172 soisdisconnected(so); 173 return (0); 174} 175 176static int 177ddp_shutdown(struct socket *so) 178{ 179 struct ddpcb *ddp; 180 181 ddp = sotoddpcb(so); 182 KASSERT(ddp != NULL, ("ddp_shutdown: ddp == NULL")); 183 184 socantsendmore(so); 185 return (0); 186} 187 188static int 189ddp_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr, 190 struct mbuf *control, struct thread *td) 191{ 192 struct ddpcb *ddp; 193 int error = 0; 194 195 ddp = sotoddpcb(so); 196 KASSERT(ddp != NULL, ("ddp_send: ddp == NULL")); 197 198 if (control && control->m_len) 199 return (EINVAL); 200 201 if (addr != NULL) { 202 DDP_LIST_XLOCK(); 203 DDP_LOCK(ddp); 204 if (ddp->ddp_fsat.sat_port != ATADDR_ANYPORT) { 205 error = EISCONN; 206 goto out; 207 } 208 209 error = at_pcbconnect(ddp, addr, td); 210 if (error == 0) { 211 error = ddp_output(m, so); 212 at_pcbdisconnect(ddp); 213 } 214out: 215 DDP_UNLOCK(ddp); 216 DDP_LIST_XUNLOCK(); 217 } else { 218 DDP_LOCK(ddp); 219 if (ddp->ddp_fsat.sat_port == ATADDR_ANYPORT) 220 error = ENOTCONN; 221 else 222 error = ddp_output(m, so); 223 DDP_UNLOCK(ddp); 224 } 225 return (error); 226} 227 228/* 229 * XXXRW: This is never called because we only invoke abort on stream 230 * protocols. 231 */ 232static void 233ddp_abort(struct socket *so) 234{ 235 struct ddpcb *ddp; 236 237 ddp = sotoddpcb(so); 238 KASSERT(ddp != NULL, ("ddp_abort: ddp == NULL")); 239 240 DDP_LOCK(ddp); 241 at_pcbdisconnect(ddp); 242 DDP_UNLOCK(ddp); 243 soisdisconnected(so); 244} 245 246static void 247ddp_close(struct socket *so) 248{ 249 struct ddpcb *ddp; 250 251 ddp = sotoddpcb(so); 252 KASSERT(ddp != NULL, ("ddp_close: ddp == NULL")); 253 254 DDP_LOCK(ddp); 255 at_pcbdisconnect(ddp); 256 DDP_UNLOCK(ddp); 257 soisdisconnected(so); 258} 259 260void 261ddp_init(void) 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 ddpcb *ddp; 280 281 for (ddp = ddpcb_list; ddp != NULL; ddp = ddp->ddp_next) { 282 at_pcbdetach(ddp->ddp_socket, ddp); 283 } 284 DDP_LIST_LOCK_DESTROY(); 285} 286#endif 287 288static int 289at_setpeeraddr(struct socket *so, struct sockaddr **nam) 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