1 /* 2 * Copyright (c) 1980, 1986 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that this notice is preserved and that due credit is given 7 * to the University of California at Berkeley. The name of the University 8 * may not be used to endorse or promote products derived from this 9 * software without specific prior written permission. This software 10 * is provided ``as is'' without express or implied warranty. 11 * 12 * @(#)raw_usrreq.c 7.3 (Berkeley) 12/30/87 13 */ 14 15 #include "param.h" 16 #include "mbuf.h" 17 #include "domain.h" 18 #include "protosw.h" 19 #include "socket.h" 20 #include "socketvar.h" 21 #include "errno.h" 22 23 #include "if.h" 24 #include "route.h" 25 #include "netisr.h" 26 #include "raw_cb.h" 27 28 #include "../machine/mtpr.h" 29 30 /* 31 * Initialize raw connection block q. 32 */ 33 raw_init() 34 { 35 36 rawcb.rcb_next = rawcb.rcb_prev = &rawcb; 37 rawintrq.ifq_maxlen = IFQ_MAXLEN; 38 } 39 40 /* 41 * Raw protocol interface. 42 */ 43 raw_input(m0, proto, src, dst) 44 struct mbuf *m0; 45 struct sockproto *proto; 46 struct sockaddr *src, *dst; 47 { 48 register struct mbuf *m; 49 struct raw_header *rh; 50 int s; 51 52 /* 53 * Rip off an mbuf for a generic header. 54 */ 55 m = m_get(M_DONTWAIT, MT_HEADER); 56 if (m == 0) { 57 m_freem(m0); 58 return; 59 } 60 m->m_next = m0; 61 m->m_len = sizeof(struct raw_header); 62 rh = mtod(m, struct raw_header *); 63 rh->raw_dst = *dst; 64 rh->raw_src = *src; 65 rh->raw_proto = *proto; 66 67 /* 68 * Header now contains enough info to decide 69 * which socket to place packet in (if any). 70 * Queue it up for the raw protocol process 71 * running at software interrupt level. 72 */ 73 s = splimp(); 74 if (IF_QFULL(&rawintrq)) 75 m_freem(m); 76 else 77 IF_ENQUEUE(&rawintrq, m); 78 splx(s); 79 schednetisr(NETISR_RAW); 80 } 81 82 /* 83 * Raw protocol input routine. Process packets entered 84 * into the queue at interrupt time. Find the socket 85 * associated with the packet(s) and move them over. If 86 * nothing exists for this packet, drop it. 87 */ 88 rawintr() 89 { 90 int s; 91 struct mbuf *m; 92 register struct rawcb *rp; 93 register struct raw_header *rh; 94 struct socket *last; 95 96 next: 97 s = splimp(); 98 IF_DEQUEUE(&rawintrq, m); 99 splx(s); 100 if (m == 0) 101 return; 102 rh = mtod(m, struct raw_header *); 103 last = 0; 104 for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) { 105 if (rp->rcb_proto.sp_family != rh->raw_proto.sp_family) 106 continue; 107 if (rp->rcb_proto.sp_protocol && 108 rp->rcb_proto.sp_protocol != rh->raw_proto.sp_protocol) 109 continue; 110 /* 111 * We assume the lower level routines have 112 * placed the address in a canonical format 113 * suitable for a structure comparison. 114 */ 115 #define equal(a1, a2) \ 116 (bcmp((caddr_t)&(a1), (caddr_t)&(a2), sizeof (struct sockaddr)) == 0) 117 if ((rp->rcb_flags & RAW_LADDR) && 118 !equal(rp->rcb_laddr, rh->raw_dst)) 119 continue; 120 if ((rp->rcb_flags & RAW_FADDR) && 121 !equal(rp->rcb_faddr, rh->raw_src)) 122 continue; 123 if (last) { 124 struct mbuf *n; 125 if (n = m_copy(m->m_next, 0, (int)M_COPYALL)) { 126 if (sbappendaddr(&last->so_rcv, &rh->raw_src, 127 n, (struct mbuf *)0) == 0) 128 /* should notify about lost packet */ 129 m_freem(n); 130 else 131 sorwakeup(last); 132 } 133 } 134 last = rp->rcb_socket; 135 } 136 if (last) { 137 if (sbappendaddr(&last->so_rcv, &rh->raw_src, 138 m->m_next, (struct mbuf *)0) == 0) 139 m_freem(m->m_next); 140 else 141 sorwakeup(last); 142 (void) m_free(m); /* header */ 143 } else 144 m_freem(m); 145 goto next; 146 } 147 148 /*ARGSUSED*/ 149 raw_ctlinput(cmd, arg) 150 int cmd; 151 struct sockaddr *arg; 152 { 153 154 if (cmd < 0 || cmd > PRC_NCMDS) 155 return; 156 /* INCOMPLETE */ 157 } 158 159 /*ARGSUSED*/ 160 raw_usrreq(so, req, m, nam, rights) 161 struct socket *so; 162 int req; 163 struct mbuf *m, *nam, *rights; 164 { 165 register struct rawcb *rp = sotorawcb(so); 166 register int error = 0; 167 168 if (req == PRU_CONTROL) 169 return (EOPNOTSUPP); 170 if (rights && rights->m_len) { 171 error = EOPNOTSUPP; 172 goto release; 173 } 174 if (rp == 0 && req != PRU_ATTACH) { 175 error = EINVAL; 176 goto release; 177 } 178 switch (req) { 179 180 /* 181 * Allocate a raw control block and fill in the 182 * necessary info to allow packets to be routed to 183 * the appropriate raw interface routine. 184 */ 185 case PRU_ATTACH: 186 if ((so->so_state & SS_PRIV) == 0) { 187 error = EACCES; 188 break; 189 } 190 if (rp) { 191 error = EINVAL; 192 break; 193 } 194 error = raw_attach(so, (int)nam); 195 break; 196 197 /* 198 * Destroy state just before socket deallocation. 199 * Flush data or not depending on the options. 200 */ 201 case PRU_DETACH: 202 if (rp == 0) { 203 error = ENOTCONN; 204 break; 205 } 206 raw_detach(rp); 207 break; 208 209 /* 210 * If a socket isn't bound to a single address, 211 * the raw input routine will hand it anything 212 * within that protocol family (assuming there's 213 * nothing else around it should go to). 214 */ 215 case PRU_CONNECT: 216 if (rp->rcb_flags & RAW_FADDR) { 217 error = EISCONN; 218 break; 219 } 220 raw_connaddr(rp, nam); 221 soisconnected(so); 222 break; 223 224 case PRU_CONNECT2: 225 error = EOPNOTSUPP; 226 goto release; 227 228 case PRU_BIND: 229 if (rp->rcb_flags & RAW_LADDR) { 230 error = EINVAL; /* XXX */ 231 break; 232 } 233 error = raw_bind(so, nam); 234 break; 235 236 case PRU_DISCONNECT: 237 if ((rp->rcb_flags & RAW_FADDR) == 0) { 238 error = ENOTCONN; 239 break; 240 } 241 raw_disconnect(rp); 242 soisdisconnected(so); 243 break; 244 245 /* 246 * Mark the connection as being incapable of further input. 247 */ 248 case PRU_SHUTDOWN: 249 socantsendmore(so); 250 break; 251 252 /* 253 * Ship a packet out. The appropriate raw output 254 * routine handles any massaging necessary. 255 */ 256 case PRU_SEND: 257 if (nam) { 258 if (rp->rcb_flags & RAW_FADDR) { 259 error = EISCONN; 260 break; 261 } 262 raw_connaddr(rp, nam); 263 } else if ((rp->rcb_flags & RAW_FADDR) == 0) { 264 error = ENOTCONN; 265 break; 266 } 267 error = (*so->so_proto->pr_output)(m, so); 268 m = NULL; 269 if (nam) 270 rp->rcb_flags &= ~RAW_FADDR; 271 break; 272 273 case PRU_ABORT: 274 raw_disconnect(rp); 275 sofree(so); 276 soisdisconnected(so); 277 break; 278 279 case PRU_SENSE: 280 /* 281 * stat: don't bother with a blocksize. 282 */ 283 return (0); 284 285 /* 286 * Not supported. 287 */ 288 case PRU_RCVOOB: 289 case PRU_RCVD: 290 return(EOPNOTSUPP); 291 292 case PRU_LISTEN: 293 case PRU_ACCEPT: 294 case PRU_SENDOOB: 295 error = EOPNOTSUPP; 296 break; 297 298 case PRU_SOCKADDR: 299 bcopy((caddr_t)&rp->rcb_laddr, mtod(nam, caddr_t), 300 sizeof (struct sockaddr)); 301 nam->m_len = sizeof (struct sockaddr); 302 break; 303 304 case PRU_PEERADDR: 305 bcopy((caddr_t)&rp->rcb_faddr, mtod(nam, caddr_t), 306 sizeof (struct sockaddr)); 307 nam->m_len = sizeof (struct sockaddr); 308 break; 309 310 default: 311 panic("raw_usrreq"); 312 } 313 release: 314 if (m != NULL) 315 m_freem(m); 316 return (error); 317 } 318