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.13 (Berkeley) 06/04/93 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 void 27 raw_init() 28 { 29 30 rawcb.rcb_next = rawcb.rcb_prev = &rawcb; 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 void 43 raw_input(m0, proto, src, dst) 44 struct mbuf *m0; 45 register struct sockproto *proto; 46 struct sockaddr *src, *dst; 47 { 48 register struct rawcb *rp; 49 register struct mbuf *m = m0; 50 register int sockets = 0; 51 struct socket *last; 52 53 last = 0; 54 for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) { 55 if (rp->rcb_proto.sp_family != proto->sp_family) 56 continue; 57 if (rp->rcb_proto.sp_protocol && 58 rp->rcb_proto.sp_protocol != proto->sp_protocol) 59 continue; 60 /* 61 * We assume the lower level routines have 62 * placed the address in a canonical format 63 * suitable for a structure comparison. 64 * 65 * Note that if the lengths are not the same 66 * the comparison will fail at the first byte. 67 */ 68 #define equal(a1, a2) \ 69 (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0) 70 if (rp->rcb_laddr && !equal(rp->rcb_laddr, dst)) 71 continue; 72 if (rp->rcb_faddr && !equal(rp->rcb_faddr, src)) 73 continue; 74 if (last) { 75 struct mbuf *n; 76 if (n = m_copy(m, 0, (int)M_COPYALL)) { 77 if (sbappendaddr(&last->so_rcv, src, 78 n, (struct mbuf *)0) == 0) 79 /* should notify about lost packet */ 80 m_freem(n); 81 else { 82 sorwakeup(last); 83 sockets++; 84 } 85 } 86 } 87 last = rp->rcb_socket; 88 } 89 if (last) { 90 if (sbappendaddr(&last->so_rcv, src, 91 m, (struct mbuf *)0) == 0) 92 m_freem(m); 93 else { 94 sorwakeup(last); 95 sockets++; 96 } 97 } else 98 m_freem(m); 99 } 100 101 /*ARGSUSED*/ 102 void 103 raw_ctlinput(cmd, arg) 104 int cmd; 105 struct sockaddr *arg; 106 { 107 108 if (cmd < 0 || cmd > PRC_NCMDS) 109 return; 110 /* INCOMPLETE */ 111 } 112 113 /*ARGSUSED*/ 114 int 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