ddp_usrreq.c revision 132009
1/* 2 * Copyright (c) 1990,1994 Regents of The University of Michigan. 3 * All Rights Reserved. See COPYRIGHT. 4 * 5 * $FreeBSD: head/sys/netatalk/ddp_usrreq.c 132009 2004-07-12 04:33:58Z rwatson $ 6 */ 7 8#include <sys/param.h> 9#include <sys/systm.h> 10#include <sys/malloc.h> 11#include <sys/mbuf.h> 12#include <sys/socket.h> 13#include <sys/socketvar.h> 14#include <sys/protosw.h> 15#include <net/if.h> 16#include <net/route.h> 17#include <net/netisr.h> 18 19#include <netatalk/at.h> 20#include <netatalk/at_var.h> 21#include <netatalk/ddp_var.h> 22#include <netatalk/ddp_pcb.h> 23#include <netatalk/at_extern.h> 24 25static u_long ddp_sendspace = DDP_MAXSZ; /* Max ddp size + 1 (ddp_type) */ 26static u_long ddp_recvspace = 10 * (587 + sizeof(struct sockaddr_at)); 27 28static struct ifqueue atintrq1, atintrq2, aarpintrq; 29 30static int 31ddp_attach(struct socket *so, int proto, struct thread *td) 32{ 33 struct ddpcb *ddp; 34 int error = 0; 35 36 37 ddp = sotoddpcb(so); 38 if (ddp != NULL) { 39 return (EINVAL); 40 } 41 42 error = at_pcballoc(so); 43 if (error) { 44 return (error); 45 } 46 return (soreserve(so, ddp_sendspace, ddp_recvspace)); 47} 48 49static int 50ddp_detach(struct socket *so) 51{ 52 struct ddpcb *ddp; 53 54 ddp = sotoddpcb(so); 55 if (ddp == NULL) { 56 return (EINVAL); 57 } 58 at_pcbdetach(so, ddp); 59 return (0); 60} 61 62static int 63ddp_bind(struct socket *so, struct sockaddr *nam, struct thread *td) 64{ 65 struct ddpcb *ddp; 66 int error = 0; 67 68 ddp = sotoddpcb(so); 69 if (ddp == NULL) { 70 return (EINVAL); 71 } 72 error = at_pcbsetaddr(ddp, nam, td); 73 return (error); 74} 75 76static int 77ddp_connect(struct socket *so, struct sockaddr *nam, struct thread *td) 78{ 79 struct ddpcb *ddp; 80 int error = 0; 81 82 ddp = sotoddpcb(so); 83 if (ddp == NULL) { 84 return (EINVAL); 85 } 86 87 if (ddp->ddp_fsat.sat_port != ATADDR_ANYPORT) { 88 return (EISCONN); 89 } 90 91 error = at_pcbconnect(ddp, nam, td); 92 if (error == 0) 93 soisconnected(so); 94 return (error); 95} 96 97static int 98ddp_disconnect(struct socket *so) 99{ 100 101 struct ddpcb *ddp; 102 103 ddp = sotoddpcb(so); 104 if (ddp == NULL) { 105 return (EINVAL); 106 } 107 if (ddp->ddp_fsat.sat_addr.s_node == ATADDR_ANYNODE) { 108 return (ENOTCONN); 109 } 110 111 at_pcbdisconnect(ddp); 112 ddp->ddp_fsat.sat_addr.s_node = ATADDR_ANYNODE; 113 soisdisconnected(so); 114 return (0); 115} 116 117static int 118ddp_shutdown(struct socket *so) 119{ 120 struct ddpcb *ddp; 121 122 ddp = sotoddpcb(so); 123 if (ddp == NULL) { 124 return (EINVAL); 125 } 126 socantsendmore(so); 127 return (0); 128} 129 130static int 131ddp_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr, 132 struct mbuf *control, struct thread *td) 133{ 134 struct ddpcb *ddp; 135 int error = 0; 136 137 ddp = sotoddpcb(so); 138 if (ddp == NULL) { 139 return (EINVAL); 140 } 141 142 if (control && control->m_len) { 143 return (EINVAL); 144 } 145 146 if (addr != NULL) { 147 if (ddp->ddp_fsat.sat_port != ATADDR_ANYPORT) { 148 return (EISCONN); 149 } 150 151 error = at_pcbconnect(ddp, addr, td); 152 if (error) { 153 return (error); 154 } 155 } else { 156 if (ddp->ddp_fsat.sat_port == ATADDR_ANYPORT) { 157 return (ENOTCONN); 158 } 159 } 160 161 error = ddp_output(m, so); 162 if (addr != NULL) { 163 at_pcbdisconnect(ddp); 164 } 165 return (error); 166} 167 168static int 169ddp_abort(struct socket *so) 170{ 171 struct ddpcb *ddp; 172 173 ddp = sotoddpcb(so); 174 if (ddp == NULL) { 175 return (EINVAL); 176 } 177 at_pcbdetach(so, ddp); 178 return (0); 179} 180 181void 182ddp_init(void) 183{ 184 185 atintrq1.ifq_maxlen = IFQ_MAXLEN; 186 atintrq2.ifq_maxlen = IFQ_MAXLEN; 187 aarpintrq.ifq_maxlen = IFQ_MAXLEN; 188 mtx_init(&atintrq1.ifq_mtx, "at1_inq", NULL, MTX_DEF); 189 mtx_init(&atintrq2.ifq_mtx, "at2_inq", NULL, MTX_DEF); 190 mtx_init(&aarpintrq.ifq_mtx, "aarp_inq", NULL, MTX_DEF); 191 netisr_register(NETISR_ATALK1, at1intr, &atintrq1, 0); 192 netisr_register(NETISR_ATALK2, at2intr, &atintrq2, 0); 193 netisr_register(NETISR_AARP, aarpintr, &aarpintrq, 0); 194} 195 196#if 0 197static void 198ddp_clean(void) 199{ 200 struct ddpcb *ddp; 201 202 for (ddp = ddpcb_list; ddp != NULL; ddp = ddp->ddp_next) { 203 at_pcbdetach(ddp->ddp_socket, ddp); 204 } 205} 206#endif 207 208static int 209at_setpeeraddr(struct socket *so, struct sockaddr **nam) 210{ 211 return (EOPNOTSUPP); 212} 213 214static int 215at_setsockaddr(struct socket *so, struct sockaddr **nam) 216{ 217 struct ddpcb *ddp; 218 219 ddp = sotoddpcb(so); 220 if (ddp == NULL) { 221 return (EINVAL); 222 } 223 at_sockaddr(ddp, nam); 224 return (0); 225} 226 227struct pr_usrreqs ddp_usrreqs = { 228 ddp_abort, 229 pru_accept_notsupp, 230 ddp_attach, 231 ddp_bind, 232 ddp_connect, 233 pru_connect2_notsupp, 234 at_control, 235 ddp_detach, 236 ddp_disconnect, 237 pru_listen_notsupp, 238 at_setpeeraddr, 239 pru_rcvd_notsupp, 240 pru_rcvoob_notsupp, 241 ddp_send, 242 pru_sense_null, 243 ddp_shutdown, 244 at_setsockaddr, 245 sosend, 246 soreceive, 247 sopoll, 248 pru_sosetlabel_null 249}; 250