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