1 /* raw_usrreq.c 4.11 82/03/19 */ 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, pf, daf, saf) 32 struct mbuf *m0; 33 struct sockproto *pf; 34 struct sockaddr *daf, *saf; 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 = *daf; 54 rh->raw_src = *saf; 55 rh->raw_protocol = *pf; 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 socket *so; 84 register struct protosw *pr; 85 register struct sockproto *sp; 86 register struct sockaddr *sa; 87 struct raw_header *rawp; 88 struct socket *last; 89 90 COUNT(RAWINTR); 91 next: 92 s = splimp(); 93 IF_DEQUEUE(&rawintrq, m); 94 splx(s); 95 if (m == 0) 96 return; 97 rawp = mtod(m, struct raw_header *); 98 sp = &rawp->raw_protocol; 99 sa = &rawp->raw_dst; 100 101 /* 102 * Find the appropriate socket(s) in which to place this 103 * packet. This is done by matching the protocol and 104 * address information prepended by raw_input against 105 * the info stored in the control block structures. 106 */ 107 last = 0; 108 for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) { 109 so = rp->rcb_socket; 110 pr = so->so_proto; 111 if (pr->pr_family != sp->sp_family || 112 (pr->pr_protocol && pr->pr_protocol != sp->sp_protocol)) 113 continue; 114 if (so->so_addr.sa_family && 115 sa->sa_family != so->so_addr.sa_family) 116 continue; 117 /* 118 * We assume the lower level routines have 119 * placed the address in a canonical format 120 * suitable for a structure comparison. Packets 121 * are duplicated for each receiving socket. 122 * 123 * SHOULD HAVE A NUMBER OF MECHANISMS FOR 124 * MATCHING BASED ON rcb_flags 125 */ 126 if ((rp->rcb_flags & RAW_ADDR) && 127 bcmp(sa->sa_data, so->so_addr.sa_data, 14) != 0) 128 continue; 129 /* 130 * To avoid extraneous packet copies, we keep 131 * track of the last socket the packet should be 132 * placed in, and make copies only after finding a 133 * socket which "collides". 134 */ 135 if (last) { 136 struct mbuf *n; 137 138 if (n = m_copy(m->m_next, 0, (int)M_COPYALL)) 139 goto nospace; 140 if (sbappendaddr(&last->so_rcv, &rawp->raw_src, n) == 0) { 141 /* 142 * Should drop notification of lost packet 143 * into this guy's queue, but... 144 */ 145 m_freem(n); 146 goto nospace; 147 } 148 sorwakeup(last); 149 } 150 nospace: 151 last = so; 152 } 153 if (last == 0) 154 goto drop; 155 if (sbappendaddr(&last->so_rcv, &rawp->raw_src, m->m_next) == 0) 156 { 157 printf("rawintr: sbappendaddr failed\n"); 158 goto drop; 159 } 160 (void) m_free(m); /* generic header */ 161 sorwakeup(last); 162 goto next; 163 drop: 164 m_freem(m); 165 goto next; 166 } 167 168 /*ARGSUSED*/ 169 raw_usrreq(so, req, m, addr) 170 struct socket *so; 171 int req; 172 struct mbuf *m; 173 caddr_t addr; 174 { 175 register struct rawcb *rp = sotorawcb(so); 176 int error = 0; 177 178 COUNT(RAW_USRREQ); 179 if (rp == 0 && req != PRU_ATTACH) 180 return (EINVAL); 181 182 switch (req) { 183 184 /* 185 * Allocate a raw control block and fill in the 186 * necessary info to allow packets to be routed to 187 * the appropriate raw interface routine. 188 */ 189 case PRU_ATTACH: 190 if ((so->so_state & SS_PRIV) == 0) 191 return (EPERM); 192 if (rp) 193 return (EINVAL); 194 error = raw_attach(so, (struct sockaddr *)addr); 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 return (ENOTCONN); 204 raw_detach(rp); 205 break; 206 207 /* 208 * If a socket isn't bound to a single address, 209 * the raw input routine will hand it anything 210 * within that protocol family (assuming there's 211 * nothing else around it should go to). 212 */ 213 case PRU_CONNECT: 214 if (rp->rcb_flags & RAW_ADDR) 215 return (EISCONN); 216 raw_connaddr(rp, (struct sockaddr *)addr); 217 soisconnected(so); 218 break; 219 220 case PRU_DISCONNECT: 221 if ((rp->rcb_flags & RAW_ADDR) == 0) 222 return (ENOTCONN); 223 raw_disconnect(rp); 224 soisdisconnected(so); 225 break; 226 227 /* 228 * Mark the connection as being incapable of further input. 229 */ 230 case PRU_SHUTDOWN: 231 socantsendmore(so); 232 break; 233 234 /* 235 * Ship a packet out. The appropriate raw output 236 * routine handles any massaging necessary. 237 */ 238 case PRU_SEND: 239 if (addr) { 240 if (rp->rcb_flags & RAW_ADDR) 241 return (EISCONN); 242 raw_connaddr(rp, (struct sockaddr *)addr); 243 } else if ((rp->rcb_flags & RAW_ADDR) == 0) 244 return (ENOTCONN); 245 (void) (*so->so_proto->pr_output)(m, so); 246 if (addr) 247 rp->rcb_flags &= ~RAW_ADDR; 248 break; 249 250 case PRU_ABORT: 251 raw_disconnect(rp); 252 sofree(so); 253 soisdisconnected(so); 254 break; 255 256 /* 257 * Not supported. 258 */ 259 case PRU_ACCEPT: 260 case PRU_RCVD: 261 case PRU_CONTROL: 262 case PRU_SENSE: 263 case PRU_RCVOOB: 264 case PRU_SENDOOB: 265 error = EOPNOTSUPP; 266 break; 267 268 default: 269 panic("raw_usrreq"); 270 } 271 return (error); 272 } 273