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