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