1 /* 2 * Copyright (c) 1980, 1986 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)raw_usrreq.c 7.9 (Berkeley) 06/28/90 8 */ 9 10 #include "param.h" 11 #include "mbuf.h" 12 #include "domain.h" 13 #include "protosw.h" 14 #include "socket.h" 15 #include "socketvar.h" 16 #include "errno.h" 17 18 #include "if.h" 19 #include "route.h" 20 #include "netisr.h" 21 #include "raw_cb.h" 22 23 #include "machine/mtpr.h" 24 25 /* 26 * Initialize raw connection block q. 27 */ 28 raw_init() 29 { 30 31 rawcb.rcb_next = rawcb.rcb_prev = &rawcb; 32 rawintrq.ifq_maxlen = IFQ_MAXLEN; 33 } 34 35 36 /* 37 * Raw protocol input routine. Find the socket 38 * associated with the packet(s) and move them over. If 39 * nothing exists for this packet, drop it. 40 */ 41 /* 42 * Raw protocol interface. 43 */ 44 raw_input(m0, proto, src, dst) 45 struct mbuf *m0; 46 register struct sockproto *proto; 47 struct sockaddr *src, *dst; 48 { 49 register struct rawcb *rp; 50 register struct mbuf *m = m0; 51 register int sockets = 0; 52 struct socket *last; 53 54 last = 0; 55 for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) { 56 if (rp->rcb_proto.sp_family != proto->sp_family) 57 continue; 58 if (rp->rcb_proto.sp_protocol && 59 rp->rcb_proto.sp_protocol != proto->sp_protocol) 60 continue; 61 /* 62 * We assume the lower level routines have 63 * placed the address in a canonical format 64 * suitable for a structure comparison. 65 * 66 * Note that if the lengths are not the same 67 * the comparison will fail at the first byte. 68 */ 69 #define equal(a1, a2) \ 70 (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0) 71 if (rp->rcb_laddr && !equal(rp->rcb_laddr, dst)) 72 continue; 73 if (rp->rcb_faddr && !equal(rp->rcb_faddr, src)) 74 continue; 75 if (last) { 76 struct mbuf *n; 77 if (n = m_copy(m, 0, (int)M_COPYALL)) { 78 if (sbappendaddr(&last->so_rcv, src, 79 n, (struct mbuf *)0) == 0) 80 /* should notify about lost packet */ 81 m_freem(n); 82 else { 83 sorwakeup(last); 84 sockets++; 85 } 86 } 87 } 88 last = rp->rcb_socket; 89 } 90 if (last) { 91 if (sbappendaddr(&last->so_rcv, src, 92 m, (struct mbuf *)0) == 0) 93 m_freem(m); 94 else { 95 sorwakeup(last); 96 sockets++; 97 } 98 } else 99 m_freem(m); 100 return (sockets); 101 } 102 103 /*ARGSUSED*/ 104 raw_ctlinput(cmd, arg) 105 int cmd; 106 struct sockaddr *arg; 107 { 108 109 if (cmd < 0 || cmd > PRC_NCMDS) 110 return; 111 /* INCOMPLETE */ 112 } 113 114 /*ARGSUSED*/ 115 raw_usrreq(so, req, m, nam, control) 116 struct socket *so; 117 int req; 118 struct mbuf *m, *nam, *control; 119 { 120 register struct rawcb *rp = sotorawcb(so); 121 register int error = 0; 122 int len; 123 124 if (req == PRU_CONTROL) 125 return (EOPNOTSUPP); 126 if (control && control->m_len) { 127 error = EOPNOTSUPP; 128 goto release; 129 } 130 if (rp == 0) { 131 error = EINVAL; 132 goto release; 133 } 134 switch (req) { 135 136 /* 137 * Allocate a raw control block and fill in the 138 * necessary info to allow packets to be routed to 139 * the appropriate raw interface routine. 140 */ 141 case PRU_ATTACH: 142 if ((so->so_state & SS_PRIV) == 0) { 143 error = EACCES; 144 break; 145 } 146 error = raw_attach(so, (int)nam); 147 break; 148 149 /* 150 * Destroy state just before socket deallocation. 151 * Flush data or not depending on the options. 152 */ 153 case PRU_DETACH: 154 if (rp == 0) { 155 error = ENOTCONN; 156 break; 157 } 158 raw_detach(rp); 159 break; 160 161 #ifdef notdef 162 /* 163 * If a socket isn't bound to a single address, 164 * the raw input routine will hand it anything 165 * within that protocol family (assuming there's 166 * nothing else around it should go to). 167 */ 168 case PRU_CONNECT: 169 if (rp->rcb_faddr) { 170 error = EISCONN; 171 break; 172 } 173 nam = m_copym(nam, 0, M_COPYALL, M_WAIT); 174 rp->rcb_faddr = mtod(nam, struct sockaddr *); 175 soisconnected(so); 176 break; 177 178 case PRU_BIND: 179 if (rp->rcb_laddr) { 180 error = EINVAL; /* XXX */ 181 break; 182 } 183 error = raw_bind(so, nam); 184 break; 185 #endif 186 187 case PRU_CONNECT2: 188 error = EOPNOTSUPP; 189 goto release; 190 191 case PRU_DISCONNECT: 192 if (rp->rcb_faddr == 0) { 193 error = ENOTCONN; 194 break; 195 } 196 raw_disconnect(rp); 197 soisdisconnected(so); 198 break; 199 200 /* 201 * Mark the connection as being incapable of further input. 202 */ 203 case PRU_SHUTDOWN: 204 socantsendmore(so); 205 break; 206 207 /* 208 * Ship a packet out. The appropriate raw output 209 * routine handles any massaging necessary. 210 */ 211 case PRU_SEND: 212 if (nam) { 213 if (rp->rcb_faddr) { 214 error = EISCONN; 215 break; 216 } 217 rp->rcb_faddr = mtod(nam, struct sockaddr *); 218 } else if (rp->rcb_faddr == 0) { 219 error = ENOTCONN; 220 break; 221 } 222 error = (*so->so_proto->pr_output)(m, so); 223 m = NULL; 224 if (nam) 225 rp->rcb_faddr = 0; 226 break; 227 228 case PRU_ABORT: 229 raw_disconnect(rp); 230 sofree(so); 231 soisdisconnected(so); 232 break; 233 234 case PRU_SENSE: 235 /* 236 * stat: don't bother with a blocksize. 237 */ 238 return (0); 239 240 /* 241 * Not supported. 242 */ 243 case PRU_RCVOOB: 244 case PRU_RCVD: 245 return(EOPNOTSUPP); 246 247 case PRU_LISTEN: 248 case PRU_ACCEPT: 249 case PRU_SENDOOB: 250 error = EOPNOTSUPP; 251 break; 252 253 case PRU_SOCKADDR: 254 if (rp->rcb_laddr == 0) { 255 error = EINVAL; 256 break; 257 } 258 len = rp->rcb_laddr->sa_len; 259 bcopy((caddr_t)rp->rcb_laddr, mtod(nam, caddr_t), (unsigned)len); 260 nam->m_len = len; 261 break; 262 263 case PRU_PEERADDR: 264 if (rp->rcb_faddr == 0) { 265 error = ENOTCONN; 266 break; 267 } 268 len = rp->rcb_faddr->sa_len; 269 bcopy((caddr_t)rp->rcb_faddr, mtod(nam, caddr_t), (unsigned)len); 270 nam->m_len = len; 271 break; 272 273 default: 274 panic("raw_usrreq"); 275 } 276 release: 277 if (m != NULL) 278 m_freem(m); 279 return (error); 280 } 281 282 rawintr() {} /* XXX - referenced by locore. will soon go away */ 283