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