1 /* raw_usrreq.c 4.13 82/04/10 */ 2 3 #include "../h/param.h" 4 #include "../h/mbuf.h" 5 #include "../h/protosw.h" 6 #include "../h/socket.h" 7 #include "../h/socketvar.h" 8 #include "../h/mtpr.h" 9 #include "../net/in.h" 10 #include "../net/in_systm.h" 11 #include "../net/if.h" 12 #include "../net/raw_cb.h" 13 #include <errno.h> 14 15 int rawqmaxlen = IFQ_MAXLEN; 16 17 /* 18 * Initialize raw connection block q. 19 */ 20 raw_init() 21 { 22 23 COUNT(RAW_INIT); 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, dst, src) 32 struct mbuf *m0; 33 struct sockproto *proto; 34 struct sockaddr *dst, *src; 35 { 36 register struct mbuf *m; 37 struct raw_header *rh; 38 int s; 39 40 COUNT(RAW_INPUT); 41 /* 42 * Rip off an mbuf for a generic header. 43 */ 44 m = m_get(M_DONTWAIT); 45 if (m == 0) { 46 m_freem(m0); 47 return; 48 } 49 m->m_next = m0; 50 m->m_off = MMINOFF; 51 m->m_len = sizeof(struct raw_header); 52 rh = mtod(m, struct raw_header *); 53 rh->raw_dst = *dst; 54 rh->raw_src = *src; 55 rh->raw_proto = *proto; 56 57 /* 58 * Header now contains enough info to decide 59 * which socket to place packet in (if any). 60 * Queue it up for the raw protocol process 61 * running at software interrupt level. 62 */ 63 s = splimp(); 64 if (IF_QFULL(&rawintrq)) 65 m_freem(m); 66 else 67 IF_ENQUEUE(&rawintrq, m); 68 splx(s); 69 schednetisr(NETISR_RAW); 70 } 71 72 /* 73 * Raw protocol input routine. Process packets entered 74 * into the queue at interrupt time. Find the socket 75 * associated with the packet(s) and move them over. If 76 * nothing exists for this packet, drop it. 77 */ 78 rawintr() 79 { 80 int s; 81 struct mbuf *m; 82 register struct rawcb *rp; 83 register struct sockaddr *laddr; 84 register struct protosw *lproto; 85 struct raw_header *rh; 86 struct socket *last; 87 88 COUNT(RAWINTR); 89 next: 90 s = splimp(); 91 IF_DEQUEUE(&rawintrq, m); 92 splx(s); 93 if (m == 0) 94 return; 95 rh = mtod(m, struct raw_header *); 96 97 /* 98 * Find the appropriate socket(s) in which to place this 99 * packet. This is done by matching the protocol and 100 * address information prepended by raw_input against 101 * the info stored in the control block structures. 102 */ 103 last = 0; 104 for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) { 105 lproto = rp->rcb_socket->so_proto; 106 if (lproto->pr_family != rh->raw_proto.sp_family) 107 continue; 108 if (lproto->pr_protocol && 109 lproto->pr_protocol != rh->raw_proto.sp_protocol) 110 continue; 111 laddr = &rp->rcb_laddr; 112 if (laddr->sa_family && 113 laddr->sa_family != rh->raw_dst.sa_family) 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 if ((rp->rcb_flags & RAW_LADDR) && 121 bcmp(laddr->sa_data, rh->raw_dst.sa_data, 14) != 0) 122 continue; 123 if ((rp->rcb_flags & RAW_FADDR) && 124 bcmp(rp->rcb_faddr.sa_data, rh->raw_src.sa_data, 14) != 0) 125 continue; 126 /* 127 * To avoid extraneous packet copies, we keep 128 * track of the last socket the packet should be 129 * placed in, and make copies only after finding a 130 * socket which "collides". 131 */ 132 if (last) { 133 struct mbuf *n; 134 135 if (n = m_copy(m->m_next, 0, (int)M_COPYALL)) 136 goto nospace; 137 if (sbappendaddr(&last->so_rcv, &rh->raw_src, n)==0) { 138 /* should notify about lost packet */ 139 m_freem(n); 140 goto nospace; 141 } 142 sorwakeup(last); 143 } 144 nospace: 145 last = rp->rcb_socket; 146 } 147 if (last == 0) 148 goto drop; 149 m = m_free(m); /* header */ 150 if (sbappendaddr(&last->so_rcv, &rh->raw_src, m) == 0) 151 goto drop; 152 sorwakeup(last); 153 goto next; 154 drop: 155 m_freem(m); 156 goto next; 157 } 158 159 /*ARGSUSED*/ 160 raw_usrreq(so, req, m, addr) 161 struct socket *so; 162 int req; 163 struct mbuf *m; 164 caddr_t addr; 165 { 166 register struct rawcb *rp = sotorawcb(so); 167 int error = 0; 168 169 COUNT(RAW_USRREQ); 170 if (rp == 0 && req != PRU_ATTACH) 171 return (EINVAL); 172 173 switch (req) { 174 175 /* 176 * Allocate a raw control block and fill in the 177 * necessary info to allow packets to be routed to 178 * the appropriate raw interface routine. 179 */ 180 case PRU_ATTACH: 181 if ((so->so_state & SS_PRIV) == 0) 182 return (EPERM); 183 if (rp) 184 return (EINVAL); 185 error = raw_attach(so, (struct sockaddr *)addr); 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 return (ENOTCONN); 195 raw_detach(rp); 196 break; 197 198 /* 199 * If a socket isn't bound to a single address, 200 * the raw input routine will hand it anything 201 * within that protocol family (assuming there's 202 * nothing else around it should go to). 203 */ 204 case PRU_CONNECT: 205 if (rp->rcb_flags & RAW_FADDR) 206 return (EISCONN); 207 raw_connaddr(rp, (struct sockaddr *)addr); 208 soisconnected(so); 209 break; 210 211 case PRU_DISCONNECT: 212 if ((rp->rcb_flags & RAW_FADDR) == 0) 213 return (ENOTCONN); 214 raw_disconnect(rp); 215 soisdisconnected(so); 216 break; 217 218 /* 219 * Mark the connection as being incapable of further input. 220 */ 221 case PRU_SHUTDOWN: 222 socantsendmore(so); 223 break; 224 225 /* 226 * Ship a packet out. The appropriate raw output 227 * routine handles any massaging necessary. 228 */ 229 case PRU_SEND: 230 if (addr) { 231 if (rp->rcb_flags & RAW_FADDR) 232 return (EISCONN); 233 raw_connaddr(rp, (struct sockaddr *)addr); 234 } else if ((rp->rcb_flags & RAW_FADDR) == 0) 235 return (ENOTCONN); 236 error = (*so->so_proto->pr_output)(m, so); 237 if (addr) 238 rp->rcb_flags &= ~RAW_FADDR; 239 break; 240 241 case PRU_ABORT: 242 raw_disconnect(rp); 243 sofree(so); 244 soisdisconnected(so); 245 break; 246 247 /* 248 * Not supported. 249 */ 250 case PRU_ACCEPT: 251 case PRU_RCVD: 252 case PRU_CONTROL: 253 case PRU_SENSE: 254 case PRU_RCVOOB: 255 case PRU_SENDOOB: 256 error = EOPNOTSUPP; 257 break; 258 259 case PRU_SOCKADDR: 260 bcopy(addr, (caddr_t)&rp->rcb_laddr, sizeof (struct sockaddr)); 261 break; 262 263 default: 264 panic("raw_usrreq"); 265 } 266 return (error); 267 } 268