1139827Simp/*- 2193219Srwatson * Copyright (c) 2004-2009 Robert N. M. Watson 3165891Srwatson * All rights reserved. 4165891Srwatson * 5165891Srwatson * Redistribution and use in source and binary forms, with or without 6165891Srwatson * modification, are permitted provided that the following conditions 7165891Srwatson * are met: 8165891Srwatson * 1. Redistributions of source code must retain the above copyright 9165891Srwatson * notice, this list of conditions and the following disclaimer. 10165891Srwatson * 2. Redistributions in binary form must reproduce the above copyright 11165891Srwatson * notice, this list of conditions and the following disclaimer in the 12165891Srwatson * documentation and/or other materials provided with the distribution. 13165891Srwatson * 14165891Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15165891Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16165891Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17165891Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18165891Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19165891Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20165891Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21165891Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22165891Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23165891Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24165891Srwatson * SUCH DAMAGE. 25165891Srwatson * 26165974Srwatson * Copyright (c) 1990, 1994 Regents of The University of Michigan. 27139827Simp * All Rights Reserved. 2867893Sphk * 29139827Simp * Permission to use, copy, modify, and distribute this software and 30139827Simp * its documentation for any purpose and without fee is hereby granted, 31139827Simp * provided that the above copyright notice appears in all copies and 32139827Simp * that both that copyright notice and this permission notice appear 33139827Simp * in supporting documentation, and that the name of The University 34139827Simp * of Michigan not be used in advertising or publicity pertaining to 35139827Simp * distribution of the software without specific, written prior 36139827Simp * permission. This software is supplied as is without expressed or 37139827Simp * implied warranties of any kind. 38139827Simp * 39139827Simp * This product includes software developed by the University of 40139827Simp * California, Berkeley and its contributors. 41139827Simp * 42139827Simp * Research Systems Unix Group 43139827Simp * The University of Michigan 44139827Simp * c/o Wesley Craig 45139827Simp * 535 W. William Street 46139827Simp * Ann Arbor, Michigan 47139827Simp * +1-313-764-2278 48139827Simp * netatalk@umich.edu 49139827Simp * 5067893Sphk * $FreeBSD$ 5115885Sjulian */ 5215885Sjulian 5315885Sjulian#include <sys/param.h> 5415885Sjulian#include <sys/systm.h> 5529024Sbde#include <sys/malloc.h> 5615885Sjulian#include <sys/mbuf.h> 5715885Sjulian#include <sys/socket.h> 5815885Sjulian#include <sys/socketvar.h> 5915885Sjulian#include <sys/protosw.h> 6015885Sjulian#include <net/if.h> 6115885Sjulian#include <net/route.h> 62111888Sjlemon#include <net/netisr.h> 6315885Sjulian 6418207Sbde#include <netatalk/at.h> 6518207Sbde#include <netatalk/at_var.h> 6618207Sbde#include <netatalk/ddp_var.h> 67127195Srwatson#include <netatalk/ddp_pcb.h> 6815885Sjulian#include <netatalk/at_extern.h> 6915885Sjulian 7033181Seivindstatic u_long ddp_sendspace = DDP_MAXSZ; /* Max ddp size + 1 (ddp_type) */ 71127288Srwatsonstatic u_long ddp_recvspace = 10 * (587 + sizeof(struct sockaddr_at)); 7215885Sjulian 73193219Srwatsonstatic const struct netisr_handler atalk1_nh = { 74193219Srwatson .nh_name = "atalk1", 75193219Srwatson .nh_handler = at1intr, 76193219Srwatson .nh_proto = NETISR_ATALK1, 77193219Srwatson .nh_policy = NETISR_POLICY_SOURCE, 78193219Srwatson}; 7925791Sjulian 80193219Srwatsonstatic const struct netisr_handler atalk2_nh = { 81193219Srwatson .nh_name = "atalk2", 82193219Srwatson .nh_handler = at2intr, 83193219Srwatson .nh_proto = NETISR_ATALK2, 84193219Srwatson .nh_policy = NETISR_POLICY_SOURCE, 85193219Srwatson}; 86193219Srwatson 87193219Srwatsonstatic const struct netisr_handler aarp_nh = { 88193219Srwatson .nh_name = "aarp", 89193219Srwatson .nh_handler = aarpintr, 90193219Srwatson .nh_proto = NETISR_AARP, 91193219Srwatson .nh_policy = NETISR_POLICY_SOURCE, 92193219Srwatson}; 93193219Srwatson 9425791Sjulianstatic int 9583366Sjulianddp_attach(struct socket *so, int proto, struct thread *td) 9615885Sjulian{ 97165974Srwatson int error = 0; 9825791Sjulian 99188124Srwatson KASSERT(sotoddpcb(so) == NULL, ("ddp_attach: ddp != NULL")); 10025791Sjulian 101132043Srwatson /* 102132043Srwatson * Allocate socket buffer space first so that it's present 103132043Srwatson * before first use. 104132043Srwatson */ 105132043Srwatson error = soreserve(so, ddp_sendspace, ddp_recvspace); 106132043Srwatson if (error) 107132043Srwatson return (error); 108132043Srwatson 109132043Srwatson DDP_LIST_XLOCK(); 110127288Srwatson error = at_pcballoc(so); 111132043Srwatson DDP_LIST_XUNLOCK(); 112132043Srwatson return (error); 11325791Sjulian} 11415885Sjulian 115157370Srwatsonstatic void 11625791Sjulianddp_detach(struct socket *so) 11725791Sjulian{ 118165974Srwatson struct ddpcb *ddp; 11925791Sjulian 120127288Srwatson ddp = sotoddpcb(so); 121156817Srwatson KASSERT(ddp != NULL, ("ddp_detach: ddp == NULL")); 122132043Srwatson 123132043Srwatson DDP_LIST_XLOCK(); 124132043Srwatson DDP_LOCK(ddp); 125127288Srwatson at_pcbdetach(so, ddp); 126132043Srwatson DDP_LIST_XUNLOCK(); 12725791Sjulian} 12815885Sjulian 12925791Sjulianstatic int 13083366Sjulianddp_bind(struct socket *so, struct sockaddr *nam, struct thread *td) 13125791Sjulian{ 132165974Srwatson struct ddpcb *ddp; 133165974Srwatson int error = 0; 13425791Sjulian 135127288Srwatson ddp = sotoddpcb(so); 136156817Srwatson KASSERT(ddp != NULL, ("ddp_bind: ddp == NULL")); 137157377Srwatson 138132043Srwatson DDP_LIST_XLOCK(); 139132043Srwatson DDP_LOCK(ddp); 14083366Sjulian error = at_pcbsetaddr(ddp, nam, td); 141132043Srwatson DDP_UNLOCK(ddp); 142132043Srwatson DDP_LIST_XUNLOCK(); 14325791Sjulian return (error); 14425791Sjulian} 14515885Sjulian 14625791Sjulianstatic int 14783366Sjulianddp_connect(struct socket *so, struct sockaddr *nam, struct thread *td) 14825791Sjulian{ 149165974Srwatson struct ddpcb *ddp; 150165974Srwatson int error = 0; 15125791Sjulian 152127288Srwatson ddp = sotoddpcb(so); 153156817Srwatson KASSERT(ddp != NULL, ("ddp_connect: ddp == NULL")); 154157377Srwatson 155132043Srwatson DDP_LIST_XLOCK(); 156132043Srwatson DDP_LOCK(ddp); 157127288Srwatson if (ddp->ddp_fsat.sat_port != ATADDR_ANYPORT) { 158165974Srwatson DDP_UNLOCK(ddp); 159165974Srwatson DDP_LIST_XUNLOCK(); 160165974Srwatson return (EISCONN); 16115885Sjulian } 16215885Sjulian 163132043Srwatson error = at_pcbconnect( ddp, nam, td ); 164132043Srwatson DDP_UNLOCK(ddp); 165132043Srwatson DDP_LIST_XUNLOCK(); 166127288Srwatson if (error == 0) 167165974Srwatson soisconnected(so); 168127288Srwatson return (error); 16925791Sjulian} 17015885Sjulian 17125791Sjulianstatic int 17225791Sjulianddp_disconnect(struct socket *so) 17325791Sjulian{ 174165974Srwatson struct ddpcb *ddp; 17525791Sjulian 176127288Srwatson ddp = sotoddpcb(so); 177156817Srwatson KASSERT(ddp != NULL, ("ddp_disconnect: ddp == NULL")); 178157377Srwatson 179132043Srwatson DDP_LOCK(ddp); 180127288Srwatson if (ddp->ddp_fsat.sat_addr.s_node == ATADDR_ANYNODE) { 181165974Srwatson DDP_UNLOCK(ddp); 182165974Srwatson return (ENOTCONN); 18315885Sjulian } 18425791Sjulian 185127288Srwatson at_pcbdisconnect(ddp); 18625791Sjulian ddp->ddp_fsat.sat_addr.s_node = ATADDR_ANYNODE; 187132043Srwatson DDP_UNLOCK(ddp); 188127288Srwatson soisdisconnected(so); 189127288Srwatson return (0); 19025791Sjulian} 19115885Sjulian 19225791Sjulianstatic int 19325791Sjulianddp_shutdown(struct socket *so) 19425791Sjulian{ 19541591Sarchie 196188124Srwatson KASSERT(sotoddpcb(so) != NULL, ("ddp_shutdown: ddp == NULL")); 197157377Srwatson 198127288Srwatson socantsendmore(so); 199127288Srwatson return (0); 20025791Sjulian} 20115885Sjulian 20225791Sjulianstatic int 20328270Swollmanddp_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr, 204165974Srwatson struct mbuf *control, struct thread *td) 20525791Sjulian{ 206165974Srwatson struct ddpcb *ddp; 207165974Srwatson int error = 0; 20825791Sjulian 209127288Srwatson ddp = sotoddpcb(so); 210156817Srwatson KASSERT(ddp != NULL, ("ddp_send: ddp == NULL")); 21115885Sjulian 212157377Srwatson if (control && control->m_len) 213127288Srwatson return (EINVAL); 21425791Sjulian 215127291Srwatson if (addr != NULL) { 216132043Srwatson DDP_LIST_XLOCK(); 217132043Srwatson DDP_LOCK(ddp); 218127288Srwatson if (ddp->ddp_fsat.sat_port != ATADDR_ANYPORT) { 219132043Srwatson error = EISCONN; 220132043Srwatson goto out; 22125791Sjulian } 22215885Sjulian 22383366Sjulian error = at_pcbconnect(ddp, addr, td); 224132043Srwatson if (error == 0) { 225132043Srwatson error = ddp_output(m, so); 226132043Srwatson at_pcbdisconnect(ddp); 22725791Sjulian } 228132043Srwatsonout: 229132043Srwatson DDP_UNLOCK(ddp); 230132043Srwatson DDP_LIST_XUNLOCK(); 23115885Sjulian } else { 232132043Srwatson DDP_LOCK(ddp); 233132043Srwatson if (ddp->ddp_fsat.sat_port == ATADDR_ANYPORT) 234132043Srwatson error = ENOTCONN; 235132043Srwatson else 236132043Srwatson error = ddp_output(m, so); 237132043Srwatson DDP_UNLOCK(ddp); 23815885Sjulian } 239127288Srwatson return (error); 24025791Sjulian} 24125791Sjulian 242160549Srwatson/* 243160549Srwatson * XXXRW: This is never called because we only invoke abort on stream 244160549Srwatson * protocols. 245160549Srwatson */ 246157366Srwatsonstatic void 24725791Sjulianddp_abort(struct socket *so) 24825791Sjulian{ 24925791Sjulian struct ddpcb *ddp; 25025791Sjulian 251127288Srwatson ddp = sotoddpcb(so); 252156817Srwatson KASSERT(ddp != NULL, ("ddp_abort: ddp == NULL")); 253157377Srwatson 254132043Srwatson DDP_LOCK(ddp); 255160549Srwatson at_pcbdisconnect(ddp); 256160549Srwatson DDP_UNLOCK(ddp); 257161002Srwatson soisdisconnected(so); 25825791Sjulian} 25915885Sjulian 260160549Srwatsonstatic void 261160549Srwatsonddp_close(struct socket *so) 262160549Srwatson{ 263160549Srwatson struct ddpcb *ddp; 264160549Srwatson 265160549Srwatson ddp = sotoddpcb(so); 266160549Srwatson KASSERT(ddp != NULL, ("ddp_close: ddp == NULL")); 267160549Srwatson 268160549Srwatson DDP_LOCK(ddp); 269160549Srwatson at_pcbdisconnect(ddp); 270160549Srwatson DDP_UNLOCK(ddp); 271161002Srwatson soisdisconnected(so); 272160549Srwatson} 273160549Srwatson 274127195Srwatsonvoid 275127195Srwatsonddp_init(void) 27615885Sjulian{ 277165974Srwatson 278132043Srwatson DDP_LIST_LOCK_INIT(); 279194913Srwatson TAILQ_INIT(&at_ifaddrhead); 280193219Srwatson netisr_register(&atalk1_nh); 281193219Srwatson netisr_register(&atalk2_nh); 282193219Srwatson netisr_register(&aarp_nh); 28315885Sjulian} 28415885Sjulian 285127195Srwatson#if 0 28615885Sjulianstatic void 287127288Srwatsonddp_clean(void) 28815885Sjulian{ 289165974Srwatson struct ddpcp *ddp; 29015885Sjulian 291165974Srwatson for (ddp = ddpcb_list; ddp != NULL; ddp = ddp->ddp_next) 292165974Srwatson at_pcbdetach(ddp->ddp_socket, ddp); 293165974Srwatson DDP_LIST_LOCK_DESTROY(); 29415885Sjulian} 295127195Srwatson#endif 29615885Sjulian 29725791Sjulianstatic int 298169462Srwatsonat_getpeeraddr(struct socket *so, struct sockaddr **nam) 29925791Sjulian{ 300165974Srwatson 301127288Srwatson return (EOPNOTSUPP); 30225791Sjulian} 30315885Sjulian 30425791Sjulianstatic int 305169462Srwatsonat_getsockaddr(struct socket *so, struct sockaddr **nam) 30625791Sjulian{ 30725791Sjulian struct ddpcb *ddp; 30841591Sarchie 309127288Srwatson ddp = sotoddpcb(so); 310169462Srwatson KASSERT(ddp != NULL, ("at_getsockaddr: ddp == NULL")); 311157130Srwatson 312132043Srwatson DDP_LOCK(ddp); 313127288Srwatson at_sockaddr(ddp, nam); 314132043Srwatson DDP_UNLOCK(ddp); 315127288Srwatson return (0); 31625791Sjulian} 31725791Sjulian 31825791Sjulianstruct pr_usrreqs ddp_usrreqs = { 319137386Sphk .pru_abort = ddp_abort, 320137386Sphk .pru_attach = ddp_attach, 321137386Sphk .pru_bind = ddp_bind, 322137386Sphk .pru_connect = ddp_connect, 323137386Sphk .pru_control = at_control, 324137386Sphk .pru_detach = ddp_detach, 325137386Sphk .pru_disconnect = ddp_disconnect, 326169462Srwatson .pru_peeraddr = at_getpeeraddr, 327137386Sphk .pru_send = ddp_send, 328137386Sphk .pru_shutdown = ddp_shutdown, 329169462Srwatson .pru_sockaddr = at_getsockaddr, 330160549Srwatson .pru_close = ddp_close, 33125791Sjulian}; 332